使用 Matplotlib 将具有不同轴的两个图合二为一

Posted

技术标签:

【中文标题】使用 Matplotlib 将具有不同轴的两个图合二为一【英文标题】:Putting two plots with different axes into one with Matplotlib 【发布时间】:2020-04-06 08:30:56 【问题描述】:

我想合并 Matplotlib 中的两个图。它们有不同的轴和刻度。这是每个人的代码。 电力图:

    #Case Study: Curtailment
from matplotlib import pyplot as plt
%matplotlib inline

load = [0, 250, 250, 250, 250, 250, 665, 2500, 2500, 2500, 2500, 2500,0,2500, 2366, 250, 250, 373, 2500,0, 2500, 0, 2500,250, 0]    
hours = list(range(25)) # [0, 1, 2, ... 22, 23, 24]
labels = [f'h:02d:00' for h in hours] # ["00:00", "01:00", ... "23:00", "24:00"]

fig = plt.figure(linewidth=1, figsize=(9, 5))
ax = plt.gca()


ax.plot(hours, load, color="goldenrod",drawstyle="steps-post",  linewidth=3) # <- drawstyle argument.
ax.set_xlabel("Time of day", fontsize=14, labelpad=8)
ax.set_ylabel("Electrical power in W", fontsize=14, labelpad=8)
ax.set_xlim(0, 24)
ax.set_ylim(0, 3000)    
plt.xticks(hours, labels=labels, rotation=90)
plt.grid(axis='y', alpha=.4)
ax.tick_params(axis='both', which='major', labelsize=14)
# (Optional) ax.legend(loc='center left', bbox_to_anchor=(0.03, 1.15), fontsize = 14, ncol=3)
plt.tight_layout() # This must be called last, after all elements (plot and legend) are ready.
plt.savefig('CS_Curtailment_ElectricalLoad.png', edgecolor='black', dpi=400, bbox_inches='tight')
plt.show()

温度图:

#Case Study: Curtailment
from matplotlib import pyplot as plt
%matplotlib inline

temperature = [
21.00,
21.02,
20.96,
20.85,
20.68,
20.46,
20.40,
20.56,
20.77,
21.06,
21.41,
21.79,
21.10,
21.57,
22.00,
21.47,
20.92,
20.46,
20.92,
20.31,
20.77,
20.35,
20.90,
21.00,
21.00
]    
hours = list(range(25)) # [0, 1, 2, ... 22, 23, 24]
labels = [f'h:02d:00' for h in hours] # ["00:00", "01:00", ... "23:00", "24:00"]

fig = plt.figure(linewidth=1, figsize=(9, 5))
ax = plt.gca()


ax.plot(hours, temperature, color="red",  linewidth=3) # <- drawstyle argument.
ax.set_xlabel("Time of day", fontsize=14, labelpad=8)
ax.set_ylabel("Temperature in °C", fontsize=14, labelpad=8)
ax.set_xlim(0, 24)
ax.set_ylim(20, 22.5)    
plt.xticks(hours, labels=labels, rotation=90)
plt.grid(axis='y', alpha=.4)
ax.tick_params(axis='both', which='major', labelsize=14)
# (Optional) ax.legend(loc='center left', bbox_to_anchor=(0.03, 1.15), fontsize = 14, ncol=3)
plt.tight_layout() # This must be called last, after all elements (plot and legend) are ready.
plt.savefig('CS_Curtailment_Temperature.png', edgecolor='black', dpi=400, bbox_inches='tight')
plt.show()

我想将电功率轴放在左侧(第一个图),将温度轴放在右侧(第二个图)。当然,这两个图具有相似的 x 轴值。 你可以用 Matplotlib 做到这一点吗?

感谢您的每一条评论。

【问题讨论】:

【参考方案1】:

是的,这可以在 matplotlib 中完成,首先生成第一个 ax(电力),然后实例化第二个轴

ax.plot(hours, load, color="goldenrod",drawstyle="steps-post",  linewidth=3)
# ... 

#generate the second instance
ax2 = ax.twinx()
ax2.plot(hours, temperature, color="red",  linewidth=3)
# ... set additional configuration for ax2

两个轴将共享相同的x-axes 和相同的fig,因此请确保在显示绘图之前以紧密布局,否则 y-label 可能会被剪裁。

fig.tight_layout()
plt.show()

编辑:

要同时处理两个轴,你需要使用图形对象,所以用它把它们保存到png 并设置图例。 legend() 方法需要接收labels,您可以在每个ax.plot( ..., label='&lt;label&gt;') 上手动设置它

    获取plt.show()之前的当前数字 使用图形对象设置图例。 使用图形对象保存图像。 显示图片。

代码:

fig = plt.gcf()
fig.legend(loc='center left', bbox_to_anchor=(0.15, 1.07), fontsize=14, ncol=3)
fig.savefig('CS_Curtailment_CombinedDiagram.png',
        edgecolor='black', dpi=400, bbox_inches='tight')
plt.show()

【讨论】:

感谢您的回答 jcaliz。基本上,这个情节在 Jupyther Notebooks 上看起来不错。不幸的是仍然有两个问题:1)当我想用命令'plt.savefig('CS_Curtailment_CombinedDiagram.png',edgecolor ='black',dpi = 400,bbox_inches ='tight')'保存文件时只有一个空图被存储。 2)我还想在情节的上缘添加一个图例。当我使用命令 'ax2.legend(loc='center left', bbox_to_anchor=(0.15, 1.07), fontsize = 14, ncol=3)' 时,我收到一条错误消息“找不到带有标签的句柄放在图例中。 " 感谢 jcaliz 的回答。现在可以保存图片了。然而,关于图例,我仍然收到相同的错误消息“没有找到带有标签的句柄放入图例。”。我刚刚将您的代码从 EDIT 部分复制并粘贴到我的代码中。 您需要在每个图上设置标签,检查每个label 参数ax.plot

以上是关于使用 Matplotlib 将具有不同轴的两个图合二为一的主要内容,如果未能解决你的问题,请参考以下文章

感谢matplotlib,如何在同一图中显示具有重叠数据的多个图形?

具有不同轴范围的熊猫平行图

Matplotlib 轴具有两个比例共享原点

怎么将origin两张图合并成一张图

Python Matplotlib饼图将两个标题相同的切片合并在一起

设置两个 matplotlib imshow 图具有相同的颜色地图比例