多个子图中的颜色条不遵循相同的比例
Color bars in multi subplots doesn't follow the same scale
我正在尝试比较四个二维直方图。我需要在这些直方图中的每一个中都有颜色条。但是,很明显,所有直方图中的色标都不相同。有办法让这个比例一样吗?
我使用的代码在下面:
plt.set_cmap('hot')
fig = plt.figure()
fig.set_size_inches(10, 10)
# Adds subplot on position 1
ax = fig.add_subplot(221,aspect='equal')
# Adds subplot on position 2
ax2 = fig.add_subplot(222, aspect='equal')
ax3 = fig.add_subplot(223, aspect='equal')
ax4 = fig.add_subplot(224, aspect='equal')
h = ax.hist2d(data,datay,bins=(100,100), rasterized=True,range=np.array([(-7.9, 7.9), (-7.9, 7.9)]))
ax.set_title('step size = 2.0 ', size= 16, fontname='Comic Sans MS')
h2 = ax2.hist2d(data2,datay2,bins=(100,100), rasterized=True,range=np.array([(-7.9, 7.9), (-7.9, 7.9)]))
ax2.set_title('step size = 5.0 ', size= 16, fontname='Comic Sans MS')
h3 = ax3.hist2d(data3,datay3,bins=(100,100), rasterized=True,range=np.array([(-7.9, 7.9), (-7.9, 7.9)]))
ax3.set_title('step size = 6.0 ', size= 16, fontname='Comic Sans MS')
h4 = ax4.hist2d(data4,datay4,bins=(100,100), rasterized=True,range=np.array([(-7.9, 7.9), (-7.9, 7.9)]))
ax4.set_title('step size = 8.0 ', size= 16, fontname='Comic Sans MS')
"""
DEFINING COLOR BARS
"""
divider = make_axes_locatable(ax)
cax = divider.append_axes('right', size='5%', pad=0.05)
fig.colorbar(h[3], cax=cax)
divider = make_axes_locatable(ax2)
cax = divider.append_axes('right', size='5%', pad=0.05)
fig.colorbar(h2[3], cax=cax)
divider = make_axes_locatable(ax3)
cax = divider.append_axes('right', size='5%', pad=0.05)
fig.colorbar(h3[3], cax=cax)
divider = make_axes_locatable(ax4)
cax = divider.append_axes('right', size='5%', pad=0.05)
fig.colorbar(h4[3], cax=cax)
ax2.set_yticks([])
ax4.set_yticks([])
plt.subplots_adjust(wspace=0.3)
plt.savefig('24pog.pdf')
plt.savefig('24pog.png')
plt.show()
您必须标准化颜色范围(查看文档中的 cmax
、cmin
。或者,您可以使用 ScalarMappable
,即
import matplotlib.pyplot as plt, numpy as np
norm = plt.cm.colors.Normalize(vmin = 0, vmax = 2)
cmap = 'hot'
sc = plt.cm.ScalarMappable(norm = norm, cmap = cmap)
fig, ax = plt.subplots(2, 2)
for idx, axi in enumerate(ax.flat):
axi.hist2d(*np.random.rand(2, 10), cmap = cmap)
fig.colorbar(sc, ax = axi)
fig.show()
plt.hist2d
的问题是,要对您的四个数据实例应用相同的“颜色缩放”,您必须事先知道四个直方图的分箱值,但您不知道这些值直到你已经绘制了直方图。
一个可能的解决方案是绘制两次直方图,第二次您将知道分箱数据的全部范围,但这似乎很浪费。
另一种方法,绘制四个直方图,读取分箱数据范围,然后更改 hist2d
返回的颜色网格的属性,但这看起来很复杂。
在我看来,最简单、最经济的方法就是自己模仿hist2d
,这里可以看到它的源代码(注:self
是一个Axes实例)
def hist2d(self, x, y, bins=10, range=None, density=False, weights=None,
cmin=None, cmax=None, **kwargs):
...
h, xedges, yedges = np.histogram2d(x, y, bins=bins, range=range,
density=density, weights=weights)
...
pc = self.pcolormesh(xedges, yedges, h.T, **kwargs)
self.set_xlim(xedges[0], xedges[-1])
self.set_ylim(yedges[0], yedges[-1])
return h, xedges, yedges, pc
嗯,没什么特别的……所以计划是在每个 x, y
实例上调用 histogram2d
,将结果保存在列表中,检查分箱数据以找到正确的规范化,最后,使用我们从 histogram2d
保存的数据,调用 pcolormesh
— 请注意,如果需要,您也可以对所有绘图使用相同的轴限制。
这是我用过的代码
In [49]: import matplotlib.pyplot as plt
...: from matplotlib.cm import ScalarMappable
...: from numpy.random import rand
...: from numpy import histogram2d
...:
...: # generate data - I have not your data…
...: data = ((rand(10000+500*i), rand(10000+500*i)) for i in range(4))
...:
...: # generate histograms (for you it's for x, y in ((x1,x2),(x2,y2),...)
...: hist = [histogram2d(x,y) for x, y in data]
...: # find min and max for each histogram
...: min_, max_ = zip(*((h.min(), h.max()) for h, xedges, yedges in hist))
...:
...: norm = plt.Normalize(min(min_), max(max_))
...: sm = ScalarMappable(norm, 'hot')
...:
...: fig, sp = plt.subplots(2, 2, constrained_layout=1)
...: sp = sp.flatten()
...: for ax, (h, xedges, yedges) in zip(sp, hist):
...: ax.pcolormesh(xedges, yedges, h.T, norm=norm, cmap='hot')
...: plt.colorbar(sm, ax=sp, aspect=30)
我正在尝试比较四个二维直方图。我需要在这些直方图中的每一个中都有颜色条。但是,很明显,所有直方图中的色标都不相同。有办法让这个比例一样吗?
我使用的代码在下面:
plt.set_cmap('hot')
fig = plt.figure()
fig.set_size_inches(10, 10)
# Adds subplot on position 1
ax = fig.add_subplot(221,aspect='equal')
# Adds subplot on position 2
ax2 = fig.add_subplot(222, aspect='equal')
ax3 = fig.add_subplot(223, aspect='equal')
ax4 = fig.add_subplot(224, aspect='equal')
h = ax.hist2d(data,datay,bins=(100,100), rasterized=True,range=np.array([(-7.9, 7.9), (-7.9, 7.9)]))
ax.set_title('step size = 2.0 ', size= 16, fontname='Comic Sans MS')
h2 = ax2.hist2d(data2,datay2,bins=(100,100), rasterized=True,range=np.array([(-7.9, 7.9), (-7.9, 7.9)]))
ax2.set_title('step size = 5.0 ', size= 16, fontname='Comic Sans MS')
h3 = ax3.hist2d(data3,datay3,bins=(100,100), rasterized=True,range=np.array([(-7.9, 7.9), (-7.9, 7.9)]))
ax3.set_title('step size = 6.0 ', size= 16, fontname='Comic Sans MS')
h4 = ax4.hist2d(data4,datay4,bins=(100,100), rasterized=True,range=np.array([(-7.9, 7.9), (-7.9, 7.9)]))
ax4.set_title('step size = 8.0 ', size= 16, fontname='Comic Sans MS')
"""
DEFINING COLOR BARS
"""
divider = make_axes_locatable(ax)
cax = divider.append_axes('right', size='5%', pad=0.05)
fig.colorbar(h[3], cax=cax)
divider = make_axes_locatable(ax2)
cax = divider.append_axes('right', size='5%', pad=0.05)
fig.colorbar(h2[3], cax=cax)
divider = make_axes_locatable(ax3)
cax = divider.append_axes('right', size='5%', pad=0.05)
fig.colorbar(h3[3], cax=cax)
divider = make_axes_locatable(ax4)
cax = divider.append_axes('right', size='5%', pad=0.05)
fig.colorbar(h4[3], cax=cax)
ax2.set_yticks([])
ax4.set_yticks([])
plt.subplots_adjust(wspace=0.3)
plt.savefig('24pog.pdf')
plt.savefig('24pog.png')
plt.show()
您必须标准化颜色范围(查看文档中的 cmax
、cmin
。或者,您可以使用 ScalarMappable
,即
import matplotlib.pyplot as plt, numpy as np
norm = plt.cm.colors.Normalize(vmin = 0, vmax = 2)
cmap = 'hot'
sc = plt.cm.ScalarMappable(norm = norm, cmap = cmap)
fig, ax = plt.subplots(2, 2)
for idx, axi in enumerate(ax.flat):
axi.hist2d(*np.random.rand(2, 10), cmap = cmap)
fig.colorbar(sc, ax = axi)
fig.show()
plt.hist2d
的问题是,要对您的四个数据实例应用相同的“颜色缩放”,您必须事先知道四个直方图的分箱值,但您不知道这些值直到你已经绘制了直方图。
一个可能的解决方案是绘制两次直方图,第二次您将知道分箱数据的全部范围,但这似乎很浪费。
另一种方法,绘制四个直方图,读取分箱数据范围,然后更改 hist2d
返回的颜色网格的属性,但这看起来很复杂。
在我看来,最简单、最经济的方法就是自己模仿hist2d
,这里可以看到它的源代码(注:self
是一个Axes实例)
def hist2d(self, x, y, bins=10, range=None, density=False, weights=None,
cmin=None, cmax=None, **kwargs):
...
h, xedges, yedges = np.histogram2d(x, y, bins=bins, range=range,
density=density, weights=weights)
...
pc = self.pcolormesh(xedges, yedges, h.T, **kwargs)
self.set_xlim(xedges[0], xedges[-1])
self.set_ylim(yedges[0], yedges[-1])
return h, xedges, yedges, pc
嗯,没什么特别的……所以计划是在每个 x, y
实例上调用 histogram2d
,将结果保存在列表中,检查分箱数据以找到正确的规范化,最后,使用我们从 histogram2d
保存的数据,调用 pcolormesh
— 请注意,如果需要,您也可以对所有绘图使用相同的轴限制。
这是我用过的代码
In [49]: import matplotlib.pyplot as plt
...: from matplotlib.cm import ScalarMappable
...: from numpy.random import rand
...: from numpy import histogram2d
...:
...: # generate data - I have not your data…
...: data = ((rand(10000+500*i), rand(10000+500*i)) for i in range(4))
...:
...: # generate histograms (for you it's for x, y in ((x1,x2),(x2,y2),...)
...: hist = [histogram2d(x,y) for x, y in data]
...: # find min and max for each histogram
...: min_, max_ = zip(*((h.min(), h.max()) for h, xedges, yedges in hist))
...:
...: norm = plt.Normalize(min(min_), max(max_))
...: sm = ScalarMappable(norm, 'hot')
...:
...: fig, sp = plt.subplots(2, 2, constrained_layout=1)
...: sp = sp.flatten()
...: for ax, (h, xedges, yedges) in zip(sp, hist):
...: ax.pcolormesh(xedges, yedges, h.T, norm=norm, cmap='hot')
...: plt.colorbar(sm, ax=sp, aspect=30)