Python 如何进行matshow或imshow,但将轴值显示为面元边界(即,与2d频率/密度图上的一样)
我需要做一个二维密度图。然而,我自己计算“密度”。所以本质上我有一个Python 如何进行matshow或imshow,但将轴值显示为面元边界(即,与2d频率/密度图上的一样),python,matplotlib,plot,histogram2d,Python,Matplotlib,Plot,Histogram2d,我需要做一个二维密度图。然而,我自己计算“密度”。所以本质上我有一个NxM值数组,我只能用plt.matshow(或imshow)来绘制 但是,在本例中,轴值是绘图中的像素,而我确实希望它显示一些用户定义的值。因此,我手动更改勾号标签,如上所述 这仍然留下了一个问题matshow仍然认为记号标签在标记图像中的“像素”,因此记号标签打印在每个像素方块的“中间”。然而,正如我所说,我真正想要绘制的更像是密度图,所以每个“像素正方形”代表x,y空间中的一个箱子。将刻度标签打印在正方形边缘上会更有意义,
NxM
值数组,我只能用plt.matshow
(或imshow)来绘制
但是,在本例中,轴值是绘图中的像素,而我确实希望它显示一些用户定义的值。因此,我手动更改勾号标签,如上所述
这仍然留下了一个问题matshow
仍然认为记号标签在标记图像中的“像素”,因此记号标签打印在每个像素方块的“中间”。然而,正如我所说,我真正想要绘制的更像是密度图,所以每个“像素正方形”代表x,y空间中的一个箱子。将刻度标签打印在正方形边缘上会更有意义,就像通常对直方图和频率图所做的那样
我应该继续使用matshow吗?还是有其他函数可以这样做?例如,我是否可以使用
plt.hist2d
手动设置“高度”,而不将数据作为一组样本输入?否则,我如何才能使plt.matshow
以我想要的方式放置记号标签?我不确定我是否正确理解您的意思。我的理解是,您希望获取数据的二维柱状图,并希望使用颜色显示每个箱子的计数/密度,同时保留箱子边缘的真实坐标
实际上,您可以结合使用numpy.historogram2d
和matplotlib.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()
哪个阴谋
棘手的部分是要获得自然输出:
- 您必须覆盖
默认设置的图像顶部原点。如前所述,这可以通过imshow
选项来实现origin='lower'
- 您必须绘制
的转置输出,因为numpy.histogram
按原样显示矩阵,而imshow
show的输出具有形状numpy.histogram
:沿x轴的值对应于行李>(nx,ny)
- 您可能必须更改纵横比,请参见
plt.imshow()的默认行为那样从-0.5开始
其中len(y_边)-1
统计我希望在y轴上显示的像素数(而y_边
是一个列表,其中包含我希望在y轴上显示的存储单元边界值,如前所述
然后我手动替换记号标签,但我还需要将它们正确映射到正确的记号
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)上放置一个点,它实际上看起来不会在下面的位置结束
是imshow
的extent
选项吗?@TomdeGeus我不这么认为。据我所知,extent只会影响图像的范围(如xlim或ylim),虽然我可能误解了它的工作原理。基本上,在关于范围的文档中,你可以在图中看到,轴实际上从-0.5开始,到6.5,而刻度标签位于像素的中心,在0.0、1.0等处。因此,如果我可以将刻度位置偏移0.5,它可以做我想要的事情(或者最好将整个图像移动-0.5像素)。谢谢你的回答,我认为它可以工作,但我仍然有一些问题(同时我正在使用matshow以防它有所不同)首先,我的x轴范围从0到40,y轴范围从0.5到3.5,所以就像你的照片一样,绘图在垂直方向上是非常压缩的。这是预期的吗?我应该尝试使用一些图形参数拉伸吗?第二:我不确定我做错了什么,但它没有在y轴上放置完整的值范围(也就是说,我手动设置了刻度标签,但它每秒钟就有一个刻度,总的来说,它的范围是我预期的一半)@关于LimokPalantaemon的纵横比:我已经更新了我的答案,包括<代码> SETIONGOND 。对于滴答声,很难说不看到实际的代码和问题。你可以考虑打开一个新的问题吗?嘿,我一直在寻找设置这个方面,但是它不适用于一个简单的<代码> Stasyaspe。ct(‘相等’).
此外,我开始相信这是一个比我最初想象的更复杂的问题。设置范围和您的答案很有帮助,但我认为在此之后还有另一步要做。我正在考虑在范围中保留“像素”的概念,而不是拉伸图形;相反,我将尝试重新标记刻度我将在下面发布一个答案(仍然保留你的答案)。两者的结合可能对其他人有所帮助
fig, ax = plt.subplots()
im = ax.matshow(value_grid, origin='lower', extent=(0, len(x_edges)-1, 0, len(y_edges)-1)
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)