如何规范热图

时间:2018-05-10 03:02:48

标签: python numpy matplotlib normalization heatmap

我正在尝试规范化从2dhistogram派生的热图。无论数据点的数量多少,我都希望分布是相对的。

附加代码包含两组数据。一个人拥有比另一个更多的x,y坐标。虽然数字是随机的,但是可以对这些图进行标准化,因此密度表示分布而不是频率。使用下面的示例,由于样本量,x1-y1似乎会有更多变化。即使潜在的变化类似于x2-y2

import matplotlib.pyplot as plt
import random
import numpy as np

fig, ((ax1, ax2)) = plt.subplots(1,2)

x1 = [random.randrange(1,101,1) for _ in range (10000)]
y1 = [random.randrange(1,101,1) for _ in range (10000)]

x2 = [random.randrange(1,100,1) for _ in range (1000)]
y2 = [random.randrange(1,100,1) for _ in range (1000)]

zi, xi, yi = np.histogram2d(x1, y1, bins=40, normed = False)
im = ax1.imshow(zi, interpolation = 'gaussian', origin = 'lower', cmap = 'jet')

zi, xi, yi = np.histogram2d(x2, y2, bins=40, normed = False)
im = ax2.imshow(zi, interpolation = 'gaussian', origin = 'lower', cmap = 'jet')

我可以通过确定每个bin中的最大强度或计数来规范化行,并将其用作参考点并绘制范围为0 - 1的其他数据吗?

注意:这与上述代码无关,但我会附上示例,以便直观地展示我希望实现的目标。我的代码生成以下图像:

enter image description here

虽然不能与上述代码重现,但这些图像是这样产生的:

C_f50,x,y,p = plt.hist2d(Con_F50X, Con_F50Y, bins = 40, range = np.array([(-85, 85), (4, 140)]))
ax9.imshow(C_f50.T, interpolation = 'gaussian', cmap = 'jet')

C_fmid,x,y,p = plt.hist2d(Con_FMIDX, Con_FMIDY, bins = 40, range = np.array([(-85, 85), (4, 140)]))
ax10.imshow(C_fmid.T, interpolation = 'gaussian', cmap = 'jet')

C_dmid,x,y,p = plt.hist2d(Con_DMIDX, Con_DMIDY, bins = 40, range = np.array([(-85, 85), (4, 140)]))
ax11.imshow(C_dmid.T, interpolation = 'gaussian', cmap = 'jet')

C_d50,x,y,p = plt.hist2d(Con_D50X, Con_D50Y, bins = 40, range = np.array([(-85, 85), (4, 140)]))
ax12.imshow(C_d50.T, interpolation = 'gaussian', cmap = 'jet')

下一组图片使用@filippo在答案部分详述的vminvmax

enter image description here

正如您所见,密度发生了显着变化。主要区别在于vmin/vmax功能。它从第一个图(C_f50)获得这些测量值。

我想要了解的是,是否有另一种方法可以从单独的点标准化所有绘图的密度。以上使用了第一个图中的vmin / vmax。但显然,如果从这个图中标准化,密度就不会发生变化。

C_f50,x,y,p = plt.hist2d(Con_F50X, Con_F50Y, bins = 40, range = np.array([(-85, 85), (4, 140)]))
ax9.imshow(C_f50.T, interpolation = 'gaussian', cmap = 'jet')

C_fmid,x,y,p = plt.hist2d(Con_FMIDX, Con_FMIDY, bins = 40, range = np.array([(-85, 85), (4, 140)]))
ax10.imshow(C_fmid.T, interpolation = 'gaussian', cmap = 'jet',vmin=C_f50.min(), vmax=C_f50.max())

C_dmid,x,y,p = plt.hist2d(Con_DMIDX, Con_DMIDY, bins = 40, range = np.array([(-85, 85), (4, 140)]))
ax11.imshow(C_dmid.T, interpolation = 'gaussian', cmap = 'jet', vmin=C_f50.min(), vmax=C_f50.max())

C_d50,x,y,p = plt.hist2d(Con_D50X, Con_D50Y, bins = 40, range = np.array([(-85, 85), (4, 140)]))
ax12.imshow(C_d50.T, interpolation = 'gaussian', cmap = 'jet',vmin=C_f50.min(), vmax=C_f50.max())

这有什么意义吗?

1 个答案:

答案 0 :(得分:1)

不确定我完全理解这个问题。附图与您发布的代码没有明显的关系。

您可以预先计算直方图,查找最小值和最大值,并使用vminvmax imshow参数进行标准化。

E.g。

import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt

# gen 9 2d gaussian samples and histogram
data = np.random.normal(size=(9, 10000, 2))
zidata = np.asarray([np.histogram2d(row[:,0], row[:,1], bins=40)[0] for row in data])

# plot 
gridspec = mpl.gridspec.GridSpec(3,3)
for zi, gs in zip(zidata, gridspec):
    ax = plt.subplot(gs)
    ax.imshow(zi, interpolation='gaussian', vmin=zidata.min(), vmax=zidata.max())
    ax.axis("tight")
plt.show()

默认情况下,imshow会使用Normalize对您的数据进行规范化,这基本上会应用简单的线性转换,如:

vmin = img.min()
vmax = img.max()
return (img - vmin)/(vmax - vmin)

您可以手动更改其行为设置vminvmax,例如在此示例中将它们设置为所有子图中的全局极值。

或者,如果您需要更多控制权,可以设置norm=matplotlib.colors.NoNorm并自行规范化数据,以便正确映射到matplotlib色彩映射。