二维图中的强度异常值(高强度的最大或最小局部峰值)

问题描述 投票:0回答:1

我想知道使用哪种方法更好地查看二维图 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()

Two outliers are presented in coordinates (2,6) and (15,2)

因此相邻 x 和 y 的 z 值远低于异常值。

我一直在研究KDE、轮廓和局部离群因子(LOF),但没有成功。实际上 KDE 工作得还不错,但是带宽极大地影响了异常值的检测。我需要在大型散点图中找到 z 值与其邻居的 z 值显着不同的点。

python algorithm scatter-plot outliers kernel-density
1个回答
1
投票

这个问题可以使用 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)]

注意

  • 边界中的任何点都不应成为输出的一部分。对吗?

  • 摩尔社区

© www.soinside.com 2019 - 2024. All rights reserved.