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

Python中移除Matplotlib柱状图白色间隙的方法咨询

解决Matplotlib柱状图白色间隙问题

问题描述

使用以下代码绘制主次坐标轴并反转Y轴时,生成的蓝色柱状图存在白色间隙,仅部分数据集能正常显示无间隙的柱状图,需要确保所有数据集生成的柱状图都能完整填充无空隙。

原代码如下:

#1 Import Library
import matplotlib.pyplot as plt
%matplotlib
import numpy as np
import pandas as pd

#2 IMPORT DATA  
sfData=pd.read_excel('data/streamflow validation.xlsx',sheet_name='Sheet1')

#3 Define Data
x = sfData['Year']
y1 = sfData['Observed']
y2 = sfData['Simulated']
y3 = sfData['Areal Rainfall']

# Or we can use loc for defining the data
x = list(sfData.iloc[:, 0])
y1 = list(sfData.iloc[:, 1])
y2 = list(sfData.iloc[:, 2])
y3 = list(sfData.iloc[:, 3])

#4 Plot Graph
fig, ax1 = plt.subplots(figsize=(12,10))
# increase space below subplot
fig.subplots_adjust(bottom=0.3)
# Twin Axes
# Secondary axes
ax2 = ax1.twinx()
ax2.bar(x, y3, width=15, bottom=0, align='center', color = 'b', data=sfData)
ax2.set_ylabel(('Areal Rainfall(mm)'),
            fontdict={'fontsize': 12})
# invert y axis
ax2.invert_yaxis()
# Primary axes
ax1.plot(x, y1, color = 'r', linestyle='dashed', linewidth=3, markersize=12)
ax1.plot(x, y2, color = 'k', linestyle='dashed', linewidth=3, markersize=12)

#5 Define Labels
ax1.set_xlabel(('Years'),
           fontdict={'fontsize': 14})
ax1.set_ylabel(('Flow (m3/s)'),
               fontdict={'fontsize': 14})

#7 Set limit 
ax1.set_ylim(0, 45)
ax2.set_ylim(800, 0)
ax1.set_xticklabels(('Jan 2003', 'Jan 2004', 'Jan 2005', 'Jan 2006', 'Jan 2007', 'Jan 2008', 'Jan 2009' ),
                    fontdict={'fontsize': 13})
for tick in ax1.get_xticklabels():
    tick.set_rotation(90)

#8 set title
ax1.set_title('Stream Flow Validation 1991', color = 'g')

#7 Display legend
legend = fig.legend()
ax1.legend(['Observed', 'Simulated'], loc='upper left', ncol=2, bbox_to_anchor=(-.01, 1.09))
ax2.legend(['Areal Rainfall'], loc='upper right', ncol=1, bbox_to_anchor=(1.01, 1.09))

#8 Saving the graph
fig.savefig('output/figure1.png')
fig.savefig('output/figure1.jpg')

问题原因

  1. 固定宽度不匹配x轴间隔:原代码中width=15是固定值,若x轴数据(如年份)的实际间隔为1,过宽的设置会导致柱子重叠或间隙;若间隔大于1,宽度不足则出现空隙。
  2. 对齐方式导致空隙:align='center'会让柱子以x轴刻度为中心,若宽度小于刻度间隔,就会出现左右空隙。
  3. 手动设置标签错位:硬编码xticklabels可能与实际x轴数据不匹配,间接导致视觉上的间隙。

解决方案

修改关键代码点

  1. 动态设置柱状图宽度:根据x轴数据的实际间隔计算宽度,确保填满每个刻度区间。
  2. 调整对齐方式:将align='center'改为align='edge',让柱子从刻度边缘开始填充。
  3. 匹配x轴刻度与数据:自动生成对应x数据的标签,避免手动硬编码导致的错位。

修改后的完整代码

#1 Import Library
import matplotlib.pyplot as plt
%matplotlib
import numpy as np
import pandas as pd

#2 IMPORT DATA  
sfData=pd.read_excel('data/streamflow validation.xlsx',sheet_name='Sheet1')

#3 Define Data
x = sfData['Year']
y1 = sfData['Observed']
y2 = sfData['Simulated']
y3 = sfData['Areal Rainfall']

# Or we can use loc for defining the data
x = list(sfData.iloc[:, 0])
y1 = list(sfData.iloc[:, 1])
y2 = list(sfData.iloc[:, 2])
y3 = list(sfData.iloc[:, 3])

#4 Plot Graph
fig, ax1 = plt.subplots(figsize=(12,10))
# increase space below subplot
fig.subplots_adjust(bottom=0.3)
# Twin Axes
# Secondary axes
ax2 = ax1.twinx()

# 关键修改:根据x轴间隔动态设置宽度,对齐方式改为edge
x_interval = x[1] - x[0] if len(x) > 1 else 1
ax2.bar(x, y3, width=x_interval, bottom=0, align='edge', color='b', data=sfData)

ax2.set_ylabel('Areal Rainfall(mm)', fontdict={'fontsize': 12})
# invert y axis
ax2.invert_yaxis()
# Primary axes
ax1.plot(x, y1, color='r', linestyle='dashed', linewidth=3, markersize=12)
ax1.plot(x, y2, color='k', linestyle='dashed', linewidth=3, markersize=12)

#5 Define Labels
ax1.set_xlabel('Years', fontdict={'fontsize': 14})
ax1.set_ylabel('Flow (m3/s)', fontdict={'fontsize': 14})

#7 Set limit 
ax1.set_ylim(0, 45)
ax2.set_ylim(800, 0)

# 修改:自动生成对应x数据的标签,避免错位
xtick_labels = [f'Jan {year}' for year in x]
ax1.set_xticks(x)
ax1.set_xticklabels(xtick_labels, fontdict={'fontsize': 13})
for tick in ax1.get_xticklabels():
    tick.set_rotation(90)

#8 set title
ax1.set_title('Stream Flow Validation 1991', color='g')

#7 Display legend
# 移除冗余的fig.legend(),避免重复图例
ax1.legend(['Observed', 'Simulated'], loc='upper left', ncol=2, bbox_to_anchor=(-.01, 1.09))
ax2.legend(['Areal Rainfall'], loc='upper right', ncol=1, bbox_to_anchor=(1.01, 1.09))

#8 Saving the graph
# 添加bbox_inches='tight'防止图例被截断
fig.savefig('output/figure1.png', bbox_inches='tight')
fig.savefig('output/figure1.jpg', bbox_inches='tight')

额外说明

  • 如果x轴是日期类型,建议将x转换为datetime格式,Matplotlib会自动处理刻度和宽度,进一步避免间隙问题。
  • 若需要柱子完全贴合无任何空隙,可将宽度设置为略大于x轴间隔(如x_interval * 1.01),但需注意避免柱子重叠。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 09:26:13