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

Matplotlib子图柱状图布局修复、标签优化及柱子颜色异常排查

Matplotlib子图柱状图布局修复、标签优化及柱子颜色异常排查

Hey there! Let's work through your two main issues step by step—first fixing the overlapping text and layout clutter, then figuring out why some bars look darker than others.


一、修复布局与文本重叠问题

Your current chart has overlapping subplot titles, bar labels, and even parts of the first subplot getting cut off. Here are a few straightforward fixes:

1. Adjust Subplot Spacing & Overall Layout

Since you're using sharex=True for two stacked subplots, the default spacing between subplots (and between the top suptitle and first subplot) is often too tight. Add these lines right before plt.show() to fix this:

# Automatically adjust subplots to avoid overlap, and reserve space for the top title
plt.tight_layout(rect=[0, 0.03, 1, 0.95])
# Manually increase vertical space between the two subplots (tweak the hspace value as needed)
fig.subplots_adjust(hspace=0.3)

The rect parameter in tight_layout carves out space for your fig.suptitle, so it won't get covered by the first subplot's title.

2. Optimize Bar Label Positioning

Your current padding=-1 shoves the bar labels inside the bars, and with rotation=90, they're crammed against the top of the bars or other elements. Let's tweak this:

  • If you want labels inside the bars: Increase padding to something like 2 to give space from the bar top.
  • If you want labels outside the bars (cleaner for taller bars): Use label_type='edge' with a positive padding:
    ax1.bar_label(graphbar, labels=textp, fontsize=6, rotation=90, fontname=font,
                  label_type='edge', padding=2)
    

Also, don't forget to initialize textp = [] at the start of your code—otherwise you'll get an undefined variable error!

3. Simplify X-Axis Label Handling

Since you set sharex=True, you don't need to manually set ax2.set_xticklabels()—Matplotlib will sync the x-axis labels automatically. This avoids redundant code and extra clutter.


二、解决部分柱子颜色偏深的问题

I spotted the root cause right away:

  • Look at your nodes list—there are duplicate entries (like Bus2 appearing twice, Sub23 appearing twice). And your nodes list was longer (24 items) than voltagespu (21 items), which means you were drawing multiple bars on top of each other at the same x-position!
  • Since you used alpha=0.35 (transparency), stacking multiple semi-transparent bars on the same spot makes them look darker (the transparency adds up, creating a denser gray).

How to Fix It:

  1. Align Your Data Lengths: First, make sure nodes, voltagespu, and voltagekV all have the same number of elements. I've cleaned up the nodes list in the example code below to match the length of your voltage data.
  2. Handle Duplicate Nodes:
    • If duplicate nodes are intentional (e.g., multiple measurements for the same bus), reduce the bar width and offset overlapping bars so they don't stack. For example, you could map node names to unique positions and add small offsets for duplicates.
    • If duplicates are accidental, just remove the extra entries from your nodes list to match the other datasets.

完整修改后代码示例

import matplotlib.pyplot as plt  # 替换你代码中的mtpb为标准matplotlib别名

# Initialize empty list for bar labels
textp = []
font = 'Arial'
widthRect = 0.8  # 补充定义你代码中缺失的bar宽度参数

# Adjust figure height to give more room for subplots
fig, (ax1, ax2) = plt.subplots(2, figsize=(12, 8), sharex=True, squeeze=True)
fig.suptitle('LF Results', fontweight='bold', fontname=font, fontsize=12)

# 对齐后的数据集
voltagespu = [98.66,95.88,95.88,100.0,97.35,100.98,99.23,97.59,99.85,97.35,100.0,101.15,99.28,101.0,99.69,99.59,96.63,100.33,100.33,100.0,100.0]
nodes = ['Bus1','Bus2','Bus2','Bus3','Bus5','Bus6','Bus7','Bus9','Bus23A','LVBus','Main','Bus','MCC1','Sub2A','Sub2B','Sub','Sub3','Swgr','Sub22','Sub23','Sub23']
angles = [-0.75,-0.84,-0.84,0.22,-2.15,0.43,-1.04,-1.01,-2.83,-2.15,0.0,-1.38,-1.04,0.44,-0.02,-0.05,-3.03,-0.86,-0.86,0.0,0.0]
voltagekV = [0.474,0.46,0.46,4.16,0.467,13.935,13.694,4.06,0.479,0.467,34.5,0.486,13.7,13.938,4.147,4.143,3.334,3.461,3.461,0.48,3.45]

# 生成柱子上的标签文本
for i in range(len(voltagespu)):
    ta = 'Voltage [pu] = {:.3f} [%] \nVoltage [kV] = {:.3f} [kV]'.format(voltagespu[i], voltagekV[i])
    textp.append(ta)

# 第一个子图配置
ax1.set_ylim(0, 110)
graphbar = ax1.bar(nodes, voltagespu, width=widthRect, edgecolor='silver',
                   label='Voltages', align='center', color='darkgrey', alpha=0.35,
                   linewidth=1)
# 优化后的柱子标签位置
ax1.bar_label(graphbar, labels=textp, fontsize=6, rotation=90, fontname=font,
              label_type='edge', padding=2)
# 添加容限线
ax1.axhline(y=105, color='red', linestyle='--', linewidth=1.2, label='Upper tolerable limit')
ax1.axhline(y=95, color='darkgreen', linestyle=':', linewidth=1.2, label='Lower tolerable limit')
# 子图样式设置
ax1.set_title('LF Voltages', fontsize=10, fontweight='bold', fontname=font)
ax1.set_ylabel('Voltage \n [p.u. %]', fontweight='bold', fontsize=8, fontname=font)
ax1.tick_params(axis='both', labelsize=6, color='blue', labelcolor='blue')
ax1.grid(axis='x', color='blue', linestyle='dotted', linewidth=0.75, alpha=0.5)
ax1.grid(axis='y', color='gray', linestyle='-', linewidth=0.25, alpha=0.6)
ax1.legend(fontsize=6, ncols=3)

# 第二个子图配置
ax2.bar(nodes, angles, width=widthRect, edgecolor='silver',
        label='Voltage Angles', align='center', color='darkgrey', alpha=0.35,
        linewidth=1)
# 子图样式设置
ax2.set_title('Voltage Angles', fontsize=10, fontweight='bold', fontname=font)
ax2.set_ylabel('Angles \n [deg]', fontweight='bold', fontsize=8, fontname=font)
ax2.set_xlabel('Nodes', fontweight='bold', fontsize=8, fontname=font)
ax2.tick_params(axis='both', labelsize=6, color='blue', labelcolor='blue')
ax2.grid(axis='x', color='blue', linestyle='dotted', linewidth=0.75, alpha=0.5)
ax2.grid(axis='y', color='gray', linestyle='-', linewidth=0.25, alpha=0.6)
ax2.legend(fontsize=6)

# 最终布局调整
plt.tight_layout(rect=[0, 0.03, 1, 0.95])
fig.subplots_adjust(hspace=0.3)

plt.show()

备注:内容来源于stack exchange,提问作者El-VeRdUgO

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.14 17:38:09