如何进行matshow或imshow,但将轴值显示为bin边界(即,就像在2d频率/密度图上一样)

时间:2019-02-25 09:55:56

标签: python matplotlib plot histogram2d

我需要做一个二维密度图。但是,我自己计算“密度”。因此,基本上我有一个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以我想要的方式放置刻度标签?

2 个答案:

答案 0 :(得分:1)

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

实际上,您可以结合使用numpy.histogram2dmatplotlib.pyplot.imshow

  

让我从警告开始。使用imshow,您可以显示像素。因此,您隐式地假设箱沿每个轴的大小均一。它们的宽度和高度可能不同,但是每个垃圾箱的宽度/高度必须相等,以使表示更加公平。

要实现我认为您想要的功能,您将必须使用以下内容:

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()

哪些情节

enter image description here

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

  • 您必须覆盖imshow的默认设置,即将图片的原点放在图片顶部。如所示,您可以使用origin='lower'选项。
  • 您必须绘制numpy.histogram的转置输出,因为imshow照原样显示矩阵,而numpy.histogram显示的输出具有(nx, ny)形状:值沿x轴对应的行。
  • 您可能必须更改长宽比,请参见this answer

答案 1 :(得分:0)

作为@TomdeGeus答案的补充,这可能会有所帮助。由于我需要绘制一个图,其中y轴的范围从0.5扩展到3.5,而x轴的范围从0扩展到40,因此它在图像中的压缩程度非常高,因此我可能不得不强制使用宽高比,工作。它显示的刻度线也有问题。

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

因此,我仍将图像绘制在“像素”坐标上,即选择范围以使x轴和y轴计算像素,但从0开始,而不是像默认{{1}那样从-0.5开始}

plt.imshow()

fig, ax = plt.subplots() im = ax.matshow(value_grid, origin='lower', extent=(0, len(x_edges)-1, 0, len(y_edges)-1) 在y轴上计算我想要的像素数(len(y_edges) - 1是一个列表,其中包含我想像以前一样在y轴上显示的bin边界值。

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

y_edges

这保留了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) 产生的像素的平方性质,但是您要记住,仍然以像素为单位定义了基础轴(即,如果我想在坐标上放置一个点, 25.0,2.0),它看起来实际上并不会像下面那样位于该位置。

enter image description here