找到2d直方图的峰值

时间:2013-05-29 19:31:00

标签: python numpy matplotlib

我制作了一些(x, y)数据的二维直方图,我得到了一个像这样的图像:

histogram-2d

我想要一种方法来获取存储(x, y)中最大值的点的H坐标。例如,对于上面的图像,它将是两个带有aprox坐标的点:(1090, 1040)(1110, 1090)

这是我的代码:

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.cm as cm
from os import getcwd
from os.path import join, realpath, dirname

# Path to dir where this code exists.
mypath = realpath(join(getcwd(), dirname(__file__)))
myfile = 'datafile.dat'

x, y = np.loadtxt(join(mypath,myfile), usecols=(1, 2), unpack=True)

fig = plt.figure()
ax = fig.add_subplot(111)

xmin, xmax = min(x), max(x)
ymin, ymax = min(y), max(y)

rang = [[xmin, xmax], [ymin, ymax]]

binsxy = [int((xmax - xmin) / 20), int((ymax - ymin) / 20)]

H, xedges, yedges = np.histogram2d(x, y, range=rang, bins=binsxy)

extent = [yedges[0], yedges[-1], xedges[0], xedges[-1]]
cp = ax.imshow(H.transpose()[::-1], interpolation='nearest', extent=extent, cmap=cm.jet)
fig.colorbar(cp)

plt.show()

修改

我尝试过Marek和qarma发布的解决方案,试图获取垃圾箱的坐标而不是它们的索引,如下所示:

# Marek's answer
x_cent, y_cent = unravel_index(H.argmax(), H.shape)
print('Marek')
print(x_cent, y_cent)
print(xedges[x_cent], yedges[y_cent])

# qarma's answer
idx = list(H.flatten()).index(H.max())
x_cent2, y_cent2 = idx / H.shape[1], idx % H.shape[1]
local_maxs = np.argwhere(H == H.max())
print('\nqarma')
print(x_cent2, y_cent2)
print(xedges[x_cent2], yedges[y_cent2])
print(xedges[local_maxs[0,0]], yedges[local_maxs[0,1]], xedges[local_maxs[1,0]], yedges[local_maxs[1,1]])

导致:

Marek
(53, 50)
(1072.7838144329899, 1005.0837113402063)

qarma
(53, 50)
(1072.7838144329899, 1005.0837113402063)
(1072.7838144329899, 1005.0837113402063, 1092.8257731958763, 1065.3611340206187)

所以最大坐标是相同的,这是好的!现在我有一个小问题,因为如果我放大2D图,我看到坐标对于全局最大值和局部最大值都有点偏心:

enter image description here

为什么会这样?

3 个答案:

答案 0 :(得分:2)

这个问题可以帮助您:Python: get the position of the biggest item in a numpy array

您可以使用H.max()获取最大值,然后将其与H进行比较,并使用numpy.nonzero查找所有最大值的位置:numpy.nonzero(H.max() == H)。这将比H.argmax()更昂贵,但您将获得所有最大值。

答案 1 :(得分:2)

以下是您可以找到第一个全局最大值

的方法
idx = list(H.flatten()).index(H.max())
x, y = idx / H.shape[1], idx % H.shape[1]

查找所有最大值的坐标作为练习留给读者...

numpy.argwhere(H == H.max())

修改

您的代码:

H, xedges, yedges = np.histogram2d(x, y, range=rang, bins=binsxy)

此处H包含直方图值的直方图值和xedges, yedges边界。请注意,edges数组的大小比相应维度中H的大小大一个。因此:

for x, y in numpy.argwhere(H == H.max()):
    # center is between x and x+1
    print numpy.average(xedges[x:x + 2]), numpy.average(yedges[y:y + 2])

答案 2 :(得分:1)

可以使用库findpeaks

pip install findpeaks

我看不到您的数据,但让我尝试另一个类似的示例:

from findpeaks import findpeaks

raw input data

# initialize with default parameters. The "denoise" parameter can be of use in your case
fp = findpeaks()
# import 2D example dataset
img = fp.import_example()
# make the fit
fp.fit(img)
# Make plot
fp.plot()

detected peaks

持久性可用于确定峰的影响。您会看到点1、2和3显示最强的峰,然后是其余峰。

# Compute persistence
fp.plot_persistence()

persitence plot