2

我需要做一个二维密度样图。但是我自己计算“密度”。所以基本上我有一个NxM值数组,我只能用plt.matshow(或 imshow)绘制。

fig, ax = plt.subplots()
im = ax.matshow(value_array)
ax.set_xticklabels(x_edges - 2.5)
ax.set_yticklabels(y_edges - 0.25)

但是,在这种情况下,轴值是图中的像素,而我真的希望它显示一些用户定义的值。所以我手动更改上面的刻度标签。

这仍然留下一个问题。matshow仍然认为刻度标签正在标记图像中的“像素”,因此刻度标签打印在每个像素正方形的“中间”。然而,就像我说的那样,我真正想要绘制的更像是一个密度图,所以每个“像素正方形”代表 x,y 空间中的一个 bin。将刻度标签打印在方形边缘上会更有意义,就像它为直方图和频率图所做的一般方式一样。

我应该继续为此使用 matshow 还是有其他功能可以做到这一点?例如,我可以使用plt.hist2d但手动设置“高度”而不输入数据作为一堆样本吗?否则,我如何plt.matshow按照我想要的方式放置刻度标签?

4

2 回答 2

2

我不确定我是否理解正确。我的理解是,您想要获取数据的二维直方图,并希望使用颜色显示每个 bin 的计数/密度,同时保留 bin-edge 的真实坐标。

实际上,您可以使用numpy.histogram2d和的组合matplotlib.pyplot.imshow

让我从一个警告开始。随imshow你显示像素。因此,您隐含地假设箱沿每个轴的大小是一致的。它们可能具有不同的宽度和高度,但每个 bin 的宽度/高度必须相等,以便表示公平。

为了实现我认为你想要的,你必须使用这样的东西:

import matplotlib.pyplot as plt
import numpy as np

N = 100000
x = np.random.randn(N)
y = np.random.weibull(2.,N)

P, xedges, yedges = np.histogram2d(x, y, bins=(np.linspace(-4,+5,10), np.linspace(0,4,21)), density=True)

fig, ax = plt.subplots()

cax = ax.imshow(P.T, extent=(xedges[0], xedges[-1], yedges[0], yedges[-1]),
  origin='lower', interpolation='nearest', clim=(0,.4), cmap='afmhot_r')

cbar = fig.colorbar(cax,aspect=10)

ax.set_aspect('auto')

ax.set_xlabel('x')
ax.set_ylabel('y')

plt.savefig('test.png')
plt.show()

哪些地块

在此处输入图像描述

棘手的部分是要获得自然的输出:

  • 您必须覆盖imshow放置图像顶部原点的默认设置。如前所述,您可以使用该origin='lower'选项执行此操作。
  • 您必须绘制 的转置输出numpy.histogram,因为imshow按原样显示矩阵,而numpy.histogramshow 的输出具有形状(nx, ny):沿 x 轴的值对应于行。
  • 您可能必须更改纵横比,请参阅此答案
于 2019-02-25T11:15:18.040 回答
0

作为@TomdeGeus 答案的补充,这里有一些可以提供帮助的东西。因为我需要绘制一个 y 轴从 0.5 延伸到 3.5 而 x 轴从 0 延伸到 40 的图形,所以它在图像中非常压缩,我可能不得不强制纵横比,这不是工作。它显示的刻度也有问题。

但是,在固定纵横比之后,我绝对建议您遵循 Tom de Geus 的回答,这是正确的方法。

所以我仍然在“像素”坐标上绘制图像,即选择范围以便 x 轴和 y 轴计算像素,但从 0 开始,而不是像默认行为那样 -0.5plt.imshow()

fig, ax = plt.subplots()

im = ax.matshow(value_grid, origin='lower', extent=(0, len(x_edges)-1, 0, len(y_edges)-1)

wherelen(y_edges) - 1计算我想要在 y 轴上的像素数(并且y_edges是一个列表,其中包含我想像以前一样在 y 轴上显示的 bin 边界的值。

然后我手动替换刻度标签,但我还需要将它们正确映射到正确的刻度。

ax.set_xticks(list(range(len(x_edges))))
ax.set_xticklabels(x_edges)
ax.set_yticks(list(range(len(y_edges))))
ax.set_yticklabels(y_edges)

这保留了由 生成的像素的正方形性质imshow,但是您必须记住,基础轴仍然是根据像素定义的(即,如果我想在坐标 (25.0, 2.0) 上放置一个点,它不会实际上看起来它最终在下面的那个位置。

在此处输入图像描述

于 2019-02-26T14:52:11.333 回答