I wonder what kind of method better to use to see outliers on z value of 2D plot. For example, I have measurements of x and y values both in range of 1 to 16 with step of 1. Next I calculate how many observations each pair of x and y (x_n, y_n) have. That give me a grid of 16 by 16 with number of observations per pair (z). Because x and y are correlated we expect to see some pattern - some group of dots more often presented then others. Sometimes in areas where few observations expected, many can be presented. This due to equipment error. Sensor erroneously stamp some value again and again and again. What is the best method to find those errors in large data? If the grid is not 16 by 16 but 9000 x 9000. Also it is possible to use raw data - repeated x and y observations (in case of KDE).
Here is some hard-coded sandbox example:
import pandas as pd
import random
import matplotlib.pyplot as plt
# Let's make data x, y, z.
# x and y are coordinates similar to matrix coordinate
x = [i for i in range(1, 17) for j in range(16)]
y = list(range(1, 17)) * 16
# z is a set of random integer values in some range
def r_num(base_value: int, n_numbers: int):
return [random.randint(base_value, base_value + 700) for i in range(n_numbers)]
def z_make():
_z = ((r_num(2000, 16)) +
(r_num(2000, 16)) +
(r_num(2000, 2) + r_num(5000, 12) + r_num(2000, 2)) +
(r_num(2000, 2) + r_num(5000, 12) + r_num(2000, 2)) +
(r_num(2000, 2) + r_num(5000, 2) + r_num(7000, 8) + r_num(5000, 2) + r_num(2000, 2)) +
(r_num(2000, 2) + r_num(5000, 2) + r_num(7000, 1) + r_num(9000, 6) + r_num(7000, 1) + r_num(5000, 2) + r_num(2000, 2)) +
(r_num(2000, 2) + r_num(5000, 2) + r_num(7000, 1) + r_num(9000, 1) + r_num(10000, 4) + r_num(9000, 1) + r_num(7000, 1) + r_num(5000, 2) + r_num(2000, 2)) +
(r_num(2000, 2) + r_num(5000, 2) + r_num(7000, 1) + r_num(9000, 1) + r_num(10000, 1) + r_num(16000, 2) + r_num(10000, 1) + r_num(9000, 1) + r_num(7000, 1) + r_num(5000, 2) + r_num(2000, 2)))
return _z
z1 = z_make()
z2 = z_make()
z2.reverse()
z = z1 + z2
for i in ['x','y','z']:
print('Len of i:', len(eval(i)))
df = pd.DataFrame({'x': x, 'y': y, 'z': z})
# Set some outliers and missing value near outlier
df.loc[(df['x'] == 2) & (df['y'] == 6), 'z'] = 15875
df.loc[(df['x'] == 15) & (df['y'] == 2), 'z'] = 14999
df.loc[(df['x'] == 2) & (df['y'] == 7), 'z'] = None
plt.scatter(df.x, df.y, c=df.z, cmap='viridis', s=100, alpha=0.7)
# Add color bar
plt.colorbar(label='Intensity')
# Set labels and title
plt.xlabel('X Label')
plt.ylabel('Y Label')
plt.show()
So i am looking for two yellow dots on the side of the plot. Neighboring dots has value of z lower then the outliers. In one case neighbor even missing.
I have been studying KDE, contour, and Local Outlier Factor (LOF), but no success. Also i asked alike question in Stack but i wonder if CV community can propose better solution.
Actually KDE worked ok-ish, but bandwidth influence detection of the outliers dramatically. I need to find points (coordinates) where the z value is different from its neighbors’ z values in large scatter-plot.