我想知道使用哪种方法更好地查看二维图 z 值上的异常值。例如,我测量的 x 和 y 值均在 1 到 16 范围内,步长为 1。接下来,我计算每对 x 和 y (x_n, y_n) 有多少个观测值。这给了我一个 16 x 16 的网格,每对 (z) 的观测值数量。因为 x 和 y 是相关的 (~0.5),所以我们预计某些组点比其他组更频繁地出现。碰巧的是,在很少有观察结果的区域,却出现了许多观察结果。部分设备错误。在大数据中查找网格不是 16 x 16 而是 9000 x 9000 的数据的最佳方法是什么?
这是一些硬编码的沙箱示例:
import pandas as pd
import matplotlib.pyplot as plt
# Let's make data x, y, z.
x = [i for i in range(1, 17) for j in range(16)]
y = list(range(1, 17)) * 16
z = []
z = (z + [2000]*16 + [2000]*16 +
([2000]*2 + [5000]*12 + [2000]*2) +
([2000]*2 + [5000]*12 + [2000]*2) +
([2000]*2 + [5000]*2 + [7000]*8 + [5000]*2 + [2000]*2) +
([2000]*2 + [5000]*2 + [7000] + [9000]*6 + [7000] + [5000]*2 + [2000]*2) +
([2000]*2 + [5000]*2 + [7000] + [9000] + [10000]*4 + [9000] + [7000] + [5000]*2 + [2000]*2) +
([2000]*2 + [5000]*2 + [7000] + [9000] + [10000] + [16000]*2 + [10000] + [9000] + [7000] + [5000]*2 + [2000]*2))
z1 = z.copy()
z1.reverse()
z = z + z1
df = pd.DataFrame({'x': x, 'y': y, 'z': z})
import matplotlib.pyplot as plt
# Create scatter plot with color mapping
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()
df.loc[(df['x'] == 2) & (df['y'] == 6), 'z'] = 15000
df.loc[(df['x'] == 15) & (df['y'] == 2), 'z'] = 15000
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()
因此相邻 x 和 y 的 z 值远低于异常值。
我一直在研究KDE、轮廓和局部离群因子(LOF),但没有成功。实际上 KDE 工作得还不错,但是带宽极大地影响了异常值的检测。我需要在大型散点图中找到 z 值与其邻居的 z 值显着不同的点。
这个问题可以使用 O(N ^ 2) 算法来解决,N 是网格的大小。
我们检查摩尔的邻居,看看该单元格的值是否比其他单元格高得多。
import numpy as np
def find_higher_points(G, threshold):
rows, cols = G.shape
moore = ((1, 0), (1, 1), (0, 1), (-1, 1), (-1, 0), (-1, -1), (0, -1), (1, -1))
res = []
for i in range(1, rows):
for j in range(1, cols):
curr = G[i, j]
neighbors = []
for dx, dy in moore:
if 0 <= i + dx < rows and 0 <= j + dy < cols:
neighbors.append(G[i + dx, j + dy])
if curr > threshold * np.mean(neighbors):
res.append((i, j))
return res
z = []
z = (z + [2000] * 16 + [2000] * 16 +
([2000] * 2 + [5000] * 12 + [2000] * 2) +
([2000] * 2 + [5000] * 12 + [2000] * 2) +
([2000] * 2 + [5000] * 2 + [7000] * 8 + [5000] * 2 + [2000] * 2) +
([2000] * 2 + [5000] * 2 + [7000] + [9000] * 6 + [7000] + [5000] * 2 + [2000] * 2) +
([2000] * 2 + [5000] * 2 + [7000] + [9000] + [10000] * 4 + [9000] + [7000] + [5000] * 2 + [2000] * 2) +
([2000] * 2 + [5000] * 2 + [7000] + [9000] + [10000] + [16000] * 2 + [10000] + [9000] + [7000] + [5000] * 2 + [2000] * 2))
z1 = z.copy()
z1.reverse()
Y = z + z1
G_size = 16
K = [[Y[j * G_size + i] for j in range(G_size)] for i in range(G_size)]
K[2][6] = 15000
K[15][2] = 15000
K = np.array(K)
threshold = 2
print(find_higher_points(K, threshold))
[(2, 6), (15, 2)]
边界中的任何点都不应成为输出的一部分。对吗?