Matplotlib 混合子图 plot 和 pcolor(mesh) 在有 colorbar 时保持相同 x 轴长度

7 投票
1 回答
8423 浏览
提问于 2025-04-18 05:26

我在想,能不能在一个图表中同时放入用plot()画的图和用pcolormesh()画的图,并且让它们的x轴长度保持一致。

我附上了两张图片,一张是pcolormesh()的子图没有显示颜色条时,x轴长度是一样的。enter image description here 另一张是当pcolormesh()的子图缩小以适应颜色条时,颜色条是显示出来的。enter image description here

我希望能有颜色条,但它应该延伸到整个图表的长度,而不是缩小子图。

这样做有没有可能,而不需要对现有的类进行子类化?

1 个回答

12

当然,这是可能的!

这里发生的事情是,系统为颜色条创建了一个新的坐标轴,而这个空间是从你用 pcolormesh 绘制的坐标轴中挤出来的。如果你不想让它这样做,可以为颜色条指定一个坐标轴对象。或者,你也可以直接使用一个水平的颜色条。

无论如何,让我们用独立的数据来重现你的问题:

import matplotlib.pyplot as plt
import numpy as np
np.random.seed(1977)

# Generate some interesting-looking random data...
num = 200
grid = np.random.normal(0, 1, (20, num)).cumsum(axis=1).cumsum(axis=0)
x = np.linspace(0, 360, num)
y1 = np.random.normal(0, 1, num).cumsum()
y2 = np.random.normal(0, 1, num).cumsum()

# Plot on three seperate axes
fig, axes = plt.subplots(nrows=3, sharex=True)
axes[0].plot(x, y1)
axes[1].plot(x, y2)
im = axes[2].imshow(grid, extent=[0, 360, 0, 20], aspect='auto')
fig.colorbar(im)

plt.show()

在这里输入图片描述


一个快速的解决办法就是直接使用一个水平的颜色条:

import matplotlib.pyplot as plt
import numpy as np
np.random.seed(1977)

# Generate some interesting-looking random data...
num = 200
grid = np.random.normal(0, 1, (20, num)).cumsum(axis=1).cumsum(axis=0)
x = np.linspace(0, 360, num)
y1 = np.random.normal(0, 1, num).cumsum()
y2 = np.random.normal(0, 1, num).cumsum()

# Plot on three seperate axes
fig, axes = plt.subplots(nrows=3, sharex=True)
axes[0].plot(x, y1)
axes[1].plot(x, y2)
im = axes[2].imshow(grid, extent=[0, 360, 0, 20], aspect='auto')
fig.colorbar(im, orientation='horizontal')

plt.show()

在这里输入图片描述


另外,你可以手动为颜色条添加另一个坐标轴。我们还会稍微调整一下,以腾出更多空间。

(顺便提一下:在添加额外的坐标轴后,不要使用 tight_layout。因为一旦我们添加了额外的坐标轴,就不再是一个整齐的子图网格了,所以 tight_layout 将无法正确工作。不过在添加之前使用是安全的,当然你可能需要在那种情况下修改 subplots_adjust 的调用。)

import matplotlib.pyplot as plt
import numpy as np
np.random.seed(1977)

# Generate some interesting-looking random data...
num = 200
grid = np.random.normal(0, 1, (20, num)).cumsum(axis=1).cumsum(axis=0)
x = np.linspace(0, 360, num)
y1 = np.random.normal(0, 1, num).cumsum()
y2 = np.random.normal(0, 1, num).cumsum()

# Plot on three seperate axes
fig, axes = plt.subplots(nrows=3, sharex=True)
axes[0].plot(x, y1)
axes[1].plot(x, y2)
im = axes[2].imshow(grid, extent=[0, 360, 0, 20], aspect='auto')

# Make some room for the colorbar
fig.subplots_adjust(left=0.07, right=0.87)

# Add the colorbar outside...
box = axes[2].get_position()
pad, width = 0.02, 0.02
cax = fig.add_axes([box.xmax + pad, box.ymin, width, box.height])
fig.colorbar(im, cax=cax)

plt.show()

在这里输入图片描述

撰写回答