我有一个非常大的代码输出几个图,每个图运行一个函数。我将所有这些图保存在单个输出.png
文件中。根据具体情况,有时代码会保存来自所有函数的图表,有时只会保存其中的一些。
其中一个图包括一个颜色条,我想放在同一个地方里面所说的情节,无论是否所有的功能都被处理过,或者只有少数功能被处理过。
我已经尝试了我能想到的一切,但是我只是在.png
最终输出文件只包含几个图(更确切地说:不会生成包含颜色条的图下面的图。)
这是一张显示我的意思的图片:
MWE
如下。为了生成第一个文件,我绘制了所有内容,而对于第二个文件,我只是注释掉了最后八个ax*
块。
import matplotlib.pyplot as plt
import numpy as np
import matplotlib.gridspec as gridspec
# Generate random data.
x = np.random.randn(60)
y = np.random.randn(60)
z = [np.random.random() for _ in range(60)]
fig = plt.figure(figsize=(20, 35)) # create the top-level container
gs = gridspec.GridSpec(14, 8) # create a GridSpec object
ax0 = plt.subplot(gs[0:2, 0:2])
plt.scatter(x, y, s=20)
plt.ylabel('$L$', fontsize=16)
plt.xlabel('$E$', fontsize=16)
ax1 = plt.subplot(gs[0:2, 2:4])
plt.scatter(x, y, s=20)
plt.ylabel('$L$', fontsize=16)
plt.xlabel('$E$', fontsize=16)
ax2 = plt.subplot(gs[0:2, 4:6])
plt.scatter(x, y, s=20)
plt.ylabel('$L$', fontsize=16)
plt.xlabel('$E$', fontsize=16)
ax3 = plt.subplot(gs[0:2, 6:8])
plt.scatter(x, y, s=20)
plt.ylabel('$L$', fontsize=16)
plt.xlabel('$E$', fontsize=16)
ax4 = plt.subplot(gs[2:4, 0:2])
plt.scatter(x, y, s=20)
plt.ylabel('$L$', fontsize=16)
plt.xlabel('$E$', fontsize=16)
ax5 = plt.subplot(gs[2:4, 2:4])
plt.scatter(x, y, s=20)
plt.ylabel('$L$', fontsize=16)
plt.xlabel('$E$', fontsize=16)
ax6 = plt.subplot(gs[2:4, 4:6])
plt.scatter(x, y, s=20)
plt.ylabel('$L$', fontsize=16)
plt.xlabel('$E$', fontsize=16)
ax7 = plt.subplot(gs[2:4, 6:8])
plt.scatter(x, y, s=20)
plt.ylabel('$L$', fontsize=16)
plt.xlabel('$E$', fontsize=16)
ax8 = plt.subplot(gs[4:6, 0:2])
plt.scatter(x, y, s=20)
plt.ylabel('$L$', fontsize=16)
plt.xlabel('$E$', fontsize=16)
ax9 = plt.subplot(gs[4:6, 2:4])
plt.scatter(x, y, s=20)
plt.ylabel('$L$', fontsize=16)
plt.xlabel('$E$', fontsize=16)
ax10 = plt.subplot(gs[4:6, 4:6])
plt.scatter(x, y, s=20)
plt.ylabel('$L$', fontsize=16)
plt.xlabel('$E$', fontsize=16)
ax11 = plt.subplot(gs[4:6, 6:8])
plt.scatter(x, y, s=20)
plt.ylabel('$L$', fontsize=16)
plt.xlabel('$E$', fontsize=16)
ax12 = plt.subplot(gs[6:8, 0:2])
plt.scatter(x, y, s=20)
plt.ylabel('$L$', fontsize=16)
plt.xlabel('$E$', fontsize=16)
ax13 = plt.subplot(gs[6:8, 2:4])
plt.scatter(x, y, s=20)
plt.ylabel('$L$', fontsize=16)
plt.xlabel('$E$', fontsize=16)
ax14 = plt.subplot(gs[6:8, 4:6])
plt.scatter(x, y, s=20)
plt.ylabel('$L$', fontsize=16)
plt.xlabel('$E$', fontsize=16)
ax15 = plt.subplot(gs[6:8, 6:8])
plt.scatter(x, y, s=20)
plt.ylabel('$L$', fontsize=16)
plt.xlabel('$E$', fontsize=16)
ax16 = plt.subplot(gs[8:10, 0:2])
plt.scatter(x, y, s=20)
plt.ylabel('$L$', fontsize=16)
plt.xlabel('$E$', fontsize=16)
ax17 = plt.subplot(gs[8:10, 2:4])
plt.scatter(x, y, s=20)
plt.ylabel('$L$', fontsize=16)
plt.xlabel('$E$', fontsize=16)
ax18 = plt.subplot(gs[8:10, 4:6])
cm = plt.cm.get_cmap('RdYlBu_r')
plt.scatter(x, y, s=20, c=z, cmap=cm, vmin=0, vmax=1)
plt.ylabel('$L$', fontsize=16)
plt.xlabel('$E$', fontsize=16)
# Plot colorbar.
box = ax18.get_position()
cbar_posit = [box.x1 * 0.93, box.y1 * 0.94, 0.04, 0.005]
cbaxes = fig.add_axes(cbar_posit)
cbar = plt.colorbar(cax=cbaxes, ticks=[0, 1], orientation='horizontal')
cbar.ax.tick_params(labelsize=9)
ax19 = plt.subplot(gs[8:10, 6:8])
plt.scatter(x, y, s=20)
plt.ylabel('$L$', fontsize=16)
plt.xlabel('$E$', fontsize=16)
ax20 = plt.subplot(gs[10:12, 0:2])
plt.scatter(x, y, s=20)
plt.ylabel('$L$', fontsize=16)
plt.xlabel('$E$', fontsize=16)
ax21 = plt.subplot(gs[10:12, 2:4])
plt.scatter(x, y, s=20)
plt.ylabel('$L$', fontsize=16)
plt.xlabel('$E$', fontsize=16)
ax22 = plt.subplot(gs[10:12, 4:6])
plt.scatter(x, y, s=20)
plt.ylabel('$L$', fontsize=16)
plt.xlabel('$E$', fontsize=16)
ax23 = plt.subplot(gs[10:12, 6:8])
plt.scatter(x, y, s=20)
plt.ylabel('$L$', fontsize=16)
plt.xlabel('$E$', fontsize=16)
ax24 = plt.subplot(gs[12:14, 0:2])
plt.scatter(x, y, s=20)
plt.ylabel('$L$', fontsize=16)
plt.xlabel('$E$', fontsize=16)
ax25 = plt.subplot(gs[12:14, 2:4])
plt.scatter(x, y, s=20)
plt.ylabel('$L$', fontsize=16)
plt.xlabel('$E$', fontsize=16)
ax26 = plt.subplot(gs[12:14, 4:6])
plt.scatter(x, y, s=20)
plt.ylabel('$L$', fontsize=16)
plt.xlabel('$E$', fontsize=16)
ax27 = plt.subplot(gs[12:14, 6:8])
plt.scatter(x, y, s=20)
plt.ylabel('$L$', fontsize=16)
plt.xlabel('$E$', fontsize=16)
fig.tight_layout()
out_png = 'colorbar.png'
plt.savefig(out_png, dpi=150)
plt.close()
这个MWE
再现了我在实际代码中生成输出.png
文件的方式,因此显然是不必要的大代码。
由于颜色条根据ax18
图的位置定位,我希望它始终正确定位在其中的正确位置,但显然不是我&# 39;得到。
我只是希望在ax18
图中
添加
好的,我已将问题缩小到fig.tight_layout()
电话。当这被注释掉时,无论生成多少个图,颜色条都保持完美的位置。这样做的缺点是最终的图像看起来更糟糕,相邻的情节'轴重叠。
有没有办法让fig.tight_layout()
开启并仍能正确获取色条位置?
答案 0 :(得分:3)
我认为有几个问题。
如果我理解正确,您希望颜色条相对于嵌入的轴处于固定位置。
fig.tight_layout()
移动常规'轴绕。通过'定期'我的意思是颜色条是您手动创建的轴,不会受此功能的影响。 AFAIK,没有任何方法可以将一个轴固定到另一个轴上,这样如果移动第一个轴,第二个也会移动以保持其相对位置。这需要我指出您需要在调用tight_layout
后设置颜色条的位置。
然而,您仍然会遇到问题,因为您需要以绝对值设置色条的位置,而您需要相对于轴的固定位置。 您需要指定轴的实际位置。
你会怎么做:
## ...
## ...
## Your MWE starts up there...
ax18 = plt.subplot(gs[8:10, 4:6])
cm = plt.cm.get_cmap('RdYlBu_r')
sca = plt.scatter(x, y, s=20, c=z, cmap=cm, vmin=0, vmax=1)
plt.ylabel('$L$', fontsize=16)
plt.xlabel('$E$', fontsize=16)
# Plot colorbar.
#box = ax18.get_position()
#cbar_posit = [box.x1 * 0.93, box.y1 * 0.94, 0.04, 0.005]
#cbaxes = fig.add_axes(cbar_posit)
#cbar = plt.colorbar(cax=cbaxes, ticks=[0, 1], orientation='horizontal')
#cbar.ax.tick_params(labelsize=9)
## You keep creating and filling axes...
## ...
## ...
请注意,我在sca
中保存了散点图的返回值。我们需要它用于颜色条。此外,您可以删除评论的行,只是为了表明您不再需要它们。
然后,在您的脚本结束时,您可以创建de colorbar,指定其在轴内的位置和大小
## ...
## ...
## All the plots are created above...
fig.tight_layout() # You call fig.tight_layout BEFORE creating the colorbar
import matplotlib
# You input the POSITION AND DIMENSIONS RELATIVE TO THE AXES
x0, y0, width, height = [0.6, 0.9, 0.2, 0.04]
# and transform them after to get the ABSOLUTE POSITION AND DIMENSIONS
Bbox = matplotlib.transforms.Bbox.from_bounds(x0, y0, width, height)
trans = ax18.transAxes + fig.transFigure.inverted()
l, b, w, h = matplotlib.transforms.TransformedBbox(Bbox, trans).bounds
# Now just create the axes and the colorbar
cbaxes = fig.add_axes([l, b, w, h])
cbar = plt.colorbar(sca, cax=cbaxes, ticks=[0, 1], orientation='horizontal')
cbar.ax.tick_params(labelsize=9)
out_png = 'colorbar.png'
plt.savefig(out_png, dpi=150)
plt.close()
我很久以前从SO的答案中得到了坐标转换的代码,并将其保存在一些脚本中。我试着相信这个答案,但我再也找不到了,抱歉。