Python:从numpy矩阵创建2D直方图

时间:2014-11-26 18:26:05

标签: python numpy matrix matplotlib histogram

我是python的新手。

我有一个numpy矩阵,尺寸为42x42,其值在0-996范围内。我想用这个数据创建一个2D直方图。我一直在看教程,但它们似乎都展示了如何从随机数据而不是numpy矩阵创建2D直方图。

到目前为止,我已导入:

import numpy as np
import matplotlib.pyplot as plt
from matplotlib import colors

我不确定这些是否是正确的导入,我只是想从我看到的教程中学到一些东西。

我有numpy矩阵M,其中包含所有值(如上所述)。最后,我希望它看起来像这样:

2D histogram

显然,我的数据会有所不同,所以我的情节应该看起来不同。任何人都可以帮我一把吗?

编辑:出于我的目的,使用matshow的 Hooked 的示例正是我正在寻找的。

4 个答案:

答案 0 :(得分:20)

如果你有来自计数的原始数据,你可以使用plt.hexbin为你创建图(恕我直言这比方格更好):改编自hexbin的例子:< / p>

import numpy as np
import matplotlib.pyplot as plt

n = 100000
x = np.random.standard_normal(n)
y = 2.0 + 3.0 * x + 4.0 * np.random.standard_normal(n)
plt.hexbin(x,y)

plt.show()

enter image description here

如果您已经提到矩阵中的Z值,只需使用plt.imshowplt.matshow

XB = np.linspace(-1,1,20)
YB = np.linspace(-1,1,20)
X,Y = np.meshgrid(XB,YB)
Z = np.exp(-(X**2+Y**2))
plt.imshow(Z,interpolation='none')

enter image description here

答案 1 :(得分:12)

如果您不仅有2D直方图矩阵而且还有基础(x, y)数据,那么您可以根据其中的分箱计数值制作(x, y)点的散点图并为每个点着色。二维直方图矩阵:

import numpy as np
import matplotlib.pyplot as plt

n = 10000
x = np.random.standard_normal(n)
y = 2.0 + 3.0 * x + 4.0 * np.random.standard_normal(n)
xedges, yedges = np.linspace(-4, 4, 42), np.linspace(-25, 25, 42)
hist, xedges, yedges = np.histogram2d(x, y, (xedges, yedges))
xidx = np.clip(np.digitize(x, xedges), 0, hist.shape[0]-1)
yidx = np.clip(np.digitize(y, yedges), 0, hist.shape[1]-1)
c = hist[xidx, yidx]
plt.scatter(x, y, c=c)

plt.show()

Example scatter plot of 2D histogram

答案 2 :(得分:1)

@unutbu's answer包含错误:xidxyidx的计算方式错误(至少在我的数据样本中)。正确的方法应该是:

xidx = np.clip(np.digitize(x, xedges) - 1, 0, hist.shape[0] - 1)
yidx = np.clip(np.digitize(y, yedges) - 1, 0, hist.shape[1] - 1)

由于我们感兴趣的np.digitize的返回维度介于1len(xedges) - 1之间,但c = hist[xidx, yidx]需要0和{{之间的索引1}}。

以下是结果的比较。正如你所看到的那样,你会得到相似但不一样的结果。

hist.shape - 1

Same Same but Different

答案 3 :(得分:0)

我是“散布直方图”的忠实拥护者,但我认为其他解决方案不能完全使它们公正。 Here is a function来实现它们。与其他解决方案相比,此功能的主要优点是它按历史数据对点进行排序(请参见mode参数)。这意味着结果看起来更像传统的直方图(即,您不会在不同的分箱中得到标记的混乱重叠)。 The scatter-histogram

该数字的MCVE(使用my function):

import numpy as np
import matplotlib.pyplot as plt
from hist_scatter import scatter_hist2d

fig = plt.figure(figsize=[5, 4])
ax = plt.gca()

x = randgen.randn(npoint)
y = 2 + 3 * x + 4 * randgen.randn(npoint)

scat = scatter_hist2d(x, y,
                      bins=[np.linspace(-4, 4, 42),
                            np.linspace(-25, 25, 42)],
                      s=5,
                      cmap=plt.get_cmap('viridis'))
ax.axhline(0, color='k', linestyle='--', zorder=3, linewidth=0.5)
ax.axvline(0, color='k', linestyle='--', zorder=3, linewidth=0.5)
plt.colorbar(scat)

需要改进的地方吗?

此方法的主要缺点是,最密集区域中的点与较低密度区域中的点重叠,从而导致每个存储箱区域的某种程度的歪曲。我花了很多时间探索两种解决方法:

1)将较小的标记用于较高密度的纸箱

2)对每个容器应用“剪贴”蒙版

第一个gives results太疯狂了。第二个看起来不错-尤其是如果您仅剪切具有~~ 20点的垃圾箱-但它非常慢(this figure花费了大约一分钟)。

因此,最终我决定,通过仔细选择标记大小和容器大小(sbins),您可以获得视觉上令人愉悦的结果,就错误陈述数据而言,还不错。毕竟,这些2D直方图通常旨在作为基础数据的视觉辅助,而不是严格的定量表示。因此,我认为这种方法远远优于“传统2D直方图”(例如plt.hist2dplt.hexbin),并且我认为,如果您找到此页面,则您也不喜欢传统(单色)散点图。

如果我是科学之王,那么我将确保所有2D直方图在余下的时间里都一样。

相关问题