You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Matplotlib barh创建相邻子图:间距与图例问题求助

Matplotlib复刻图表的问题解决建议

问题描述

我尝试用Matplotlib复刻目标图表,但遇到两个问题:

  • 第一个子图(Alcohol部分)的条形间距无法按预期调整
  • 生成的图例没有显示所有指定标签(比如"Minor Change"无法正常显示)

以下是我尝试的代码:

import matplotlib.pyplot as plt
import numpy as np

#This style looks the best
plt.style.use('default')

#Sizes the plot nicely to see in python
plt.figure(figsize=(10,6))

labels_alcohol = ['Borchers et al.', 'Donnelly et al.']
values_alcohol = [24, 1]

labels_formalin = ['Wang and Feng', 'van Haaren et al.', 'Borchers et al.', 'Gustafson et al.', 'Ebacher et al.']
values_formalin = [3, 3, 24, 52, 52]

fig, axs = plt.subplots(2, 1, sharex=True)
# Remove vertical space between axes
fig.subplots_adjust(hspace=0)

# Plot each graph, and manually set the y tick values
axs[0].barh(labels_alcohol[0], values_alcohol[0], color='white', label='No Change', hatch="\\", edgecolor="black", height=0.2)
axs[0].barh(labels_alcohol[1], values_alcohol[1], color='white', label='Major Change', hatch="x", edgecolor="black", height=0.2)
axs[0].set_ylabel('Alcohol')

axs[1].barh(labels_formalin[0], values_formalin[0], color='white', label='_No Change', hatch="\\", edgecolor="black", height=0.8)
axs[1].barh(labels_formalin[1], values_formalin[1], color='white', label='_Major Change', hatch="x", edgecolor="black", height=0.8)
axs[1].barh(labels_formalin[2], values_formalin[2], color='white', label='Minor Change', hatch="o", edgecolor="black", height=0.8)
axs[1].barh(labels_formalin[3], values_formalin[3], color='white', label='_No Change', hatch="\\", edgecolor="black", height=0.8)
axs[1].barh(labels_formalin[4], values_formalin[4], color='white', label='_No Change', hatch="\\", edgecolor="black", height=0.8)
axs[1].set_ylabel('Formalin')

plt.xlabel('Weeks Stored')
plt.legend()

plt.savefig("Storage Protocol Plot.pdf")
plt.show()

解决方案

1. 修复第一个子图的条形间距问题

直接给barh传入标签会让Matplotlib自动分配y轴位置,间距不好控制。改用手动指定y轴位置的方式,通过调整height参数和y轴刻度来控制间距:

  • 用np.arange()生成每个条形的y轴索引
  • 设置合适的height值(比如0.6),让条形之间保留适当空白
  • 用set_yticks()把索引映射回原始标签

2. 修复图例显示不全问题

  • Matplotlib会忽略以下划线开头的标签(如_No Change),但重复标签也只会显示一次,所以只在第一次出现每个图例项时设置正常标签,后续重复项设置下划线开头的标签即可
  • 统一从两个子图中收集图例项,避免遗漏

修改后的完整代码

import matplotlib.pyplot as plt
import numpy as np

plt.style.use('default')
fig, axs = plt.subplots(2, 1, sharex=True, figsize=(10,6))
fig.subplots_adjust(hspace=0)

# 处理Alcohol子图(第一个子图)
labels_alcohol = ['Borchers et al.', 'Donnelly et al.']
values_alcohol = [24, 1]
y_alcohol = np.arange(len(labels_alcohol))
# 设置height控制条形粗细,间接调整间距
axs[0].barh(y_alcohol, values_alcohol, color='white', edgecolor="black", height=0.6)
# 单独设置每个条形的hatch和标签(仅第一次出现时设置有效标签)
axs[0].patches[0].set_hatch("\\")
axs[0].patches[0].set_label('No Change')
axs[0].patches[1].set_hatch("x")
axs[0].patches[1].set_label('Major Change')
# 映射y轴刻度到标签
axs[0].set_yticks(y_alcohol)
axs[0].set_yticklabels(labels_alcohol)
axs[0].set_ylabel('Alcohol')

# 处理Formalin子图(第二个子图)
labels_formalin = ['Wang and Feng', 'van Haaren et al.', 'Borchers et al.', 'Gustafson et al.', 'Ebacher et al.']
values_formalin = [3, 3, 24, 52, 52]
y_formalin = np.arange(len(labels_formalin))
axs[1].barh(y_formalin, values_formalin, color='white', edgecolor="black", height=0.6)
# 逐个设置hatch和标签(重复项用下划线开头避免重复图例)
axs[1].patches[0].set_hatch("\\")
axs[1].patches[0].set_label('_No Change')
axs[1].patches[1].set_hatch("x")
axs[1].patches[1].set_label('_Major Change')
axs[1].patches[2].set_hatch("o")
axs[1].patches[2].set_label('Minor Change')
axs[1].patches[3].set_hatch("\\")
axs[1].patches[3].set_label('_No Change')
axs[1].patches[4].set_hatch("\\")
axs[1].patches[4].set_label('_No Change')
# 映射y轴刻度到标签
axs[1].set_yticks(y_formalin)
axs[1].set_yticklabels(labels_formalin)
axs[1].set_ylabel('Formalin')

plt.xlabel('Weeks Stored')
# 收集所有有效图例项并显示
handles, labels = plt.gca().get_legend_handles_labels()
# 去重(确保每个标签只显示一次)
unique_labels = dict(zip(labels, handles))
plt.legend(unique_labels.values(), unique_labels.keys())

plt.savefig("Storage Protocol Plot.pdf")
plt.show()

额外优化建议

  • 如果需要更精确的条形间距,可以调整y_alcohol的数值(比如加/减偏移量)
  • 可以通过fig.subplots_adjust()的left参数调整左侧空白,避免标签被截断

内容的提问来源于stack exchange,提问作者Nicholas Daras

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 01:52:43