在两个具有相等宽高比的子图中添加色条

7
我试图为由两个具有相等纵横比的子图组成的绘图添加一个色条,即使用set_aspect('equal')

enter image description here

可以在此IPython笔记本中找到用于创建此绘图的代码。
使用下面显示的代码(以及笔记本中的这里)创建的图像是我能得到的最佳结果,但仍不完全符合我的要求。
plt.subplot(1,2,1)
plt.pcolormesh(rand1)
plt.gca().set_aspect('equal')

plt.subplot(1,2,2)
plt.pcolormesh(rand2)
plt.gca().set_aspect('equal')

plt.tight_layout()

from mpl_toolkits.axes_grid1 import make_axes_locatable
divider = make_axes_locatable(plt.gca())
cax = divider.append_axes("right", size="5%", pad=0.05)

plt.colorbar(cax=cax)

在此输入图片描述

这个问题似乎有关:


你有什么问题? - David Zwicker
1
显示效果很差 :( - Daniel Wehner
1
我不确定你想做什么。另外,你说的“显示效果不好”是什么意思? - The Dude
如果您发布的代码不是自包含的,没有显示结果并且没有描述您期望的内容,那么这并不是很有帮助。人们应该如何帮助您呢? - David Zwicker
非常抱歉,我的浏览器昨天下载图片时出现了严重问题。已更新初始评论,包含发布笔记本的链接。 - Daniel Wehner
3个回答

8

我仍然不确定您确切想要什么,但我猜您想使用pcolormesh创建子图,并添加一个颜色条使它们具有相同的大小?

目前我所拥有的方法是有些取巧的,因为我添加了两个子图的colorbar以确保它们具有相同的大小。之后我会删除第一个colorbar。如果这就是您想要的结果,我可以探索更符合Python风格的实现方式。目前还不太清楚您确切想要什么。

import numpy
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import make_axes_locatable


data = numpy.random.random((10, 10))

fig = plt.figure()

ax1 = fig.add_subplot(1,2,1, aspect = "equal")
ax2 = fig.add_subplot(1,2,2, aspect = "equal")

im1 = ax1.pcolormesh(data)
im2 = ax2.pcolormesh(data)

divider1 = make_axes_locatable(ax1)
cax1 = divider1.append_axes("right", size="5%", pad=0.05)

divider2 = make_axes_locatable(ax2)
cax2 = divider2.append_axes("right", size="5%", pad=0.05)

#Create and remove the colorbar for the first subplot
cbar1 = fig.colorbar(im1, cax = cax1)
fig.delaxes(fig.axes[2])

#Create second colorbar
cbar2 = fig.colorbar(im2, cax = cax2)

plt.tight_layout()

plt.show()

enter image description here


1
谢谢,这正是我问题的解决方案。我试图在 http://nbviewer.ipython.org/gist/dawehner/38146566287fb23def4a 上记录我的先前方法和您的解决方案。 - Daniel Wehner

4
这个解决方案与上面的解决方案类似,但不需要创建和丢弃色条。
请注意,这两种解决方案都存在潜在缺陷:色条将使用其中一个颜色网格的颜色映射和归一化。如果两者相同,则没有问题。 ImageGrid 有一个类似于您想要的东西。
from mpl_toolkits.axes_grid1 import make_axes_locatable
fig = plt.figure(1, (4., 4.))
ax = plt.subplot(1,1,1)
divider = make_axes_locatable(ax)

cm = plt.pcolormesh(rand1)
ax.set_aspect('equal')

cax = divider.append_axes("right", size="100%", pad=0.4)
plt.pcolormesh(rand2)
cax.set_aspect('equal')

sm = plt.cm.ScalarMappable(cmap=cm.cmap, norm=cm.norm)
sm._A = []

cax = divider.append_axes("right", size="10%", pad=0.1)
plt.colorbar(sm, cax=cax)
None # Prevent text output

我不同意你对潜在缺陷所发表的评论。 当使用一个 colorbar 为使用 pcolormeshimshow 创建的两个子图时,必须使两个数据集的 vminvmax 相同。否则,您甚至不能使用单个 colorbar。 如果 vminvmax 不同,则需要使用两个 colorbars,您可以单独对它们进行归一化处理。 - The Dude
一个更加整洁的写法(这在某种程度上是个人口味问题)是在最后一行加上分号(即使用 plt.colorbar(sm, cax=cax);)。 - Christian O'Reilly

1

虽然已经有一个可行的解决方案,但它还是有些 hacky。我认为更清晰的方法是使用 GridSpec。它也可以更好地适应较大的网格。

import numpy
import matplotlib.pyplot as plt
import matplotlib

nb_cols = 5
data = numpy.random.random((10, 10))

fig = plt.figure()
gs = matplotlib.gridspec.GridSpec(1, nb_cols)        
axes = [fig.add_subplot(gs[0, col], aspect="equal") for col in range(nb_cols)]

for col, ax in enumerate(axes):
    im = ax.pcolormesh(data, vmin=data.min(), vmax=data.max())
    if col > 0:
        ax.yaxis.set_visible(False)

fig.colorbar(im, ax=axes, pad=0.01, shrink=0.23)

enter image description here


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接