如何消除Matplotlib柱状图白边并合并图例?
问题解决方法
消除柱状图白边
你看到的白边是因为直接用日期作为x轴时,柱状图的宽度和月份间隔不匹配,导致柱子之间出现间隙。解决办法:
- 用整数索引(0到20)作为x轴的位置,把bar的
width设为1,让柱子紧密排列 - 再把x轴的刻度标签替换成对应的月份日期,保证图表可读性
合并图例
双轴图表的图例默认分属两个坐标轴,要合并的话,需要手动把两个轴的图例元素提取出来,再一起显示。
修改后的完整代码
import matplotlib.pyplot as plt import seaborn as sns import pandas as pd # 先确保日期列是datetime类型 df2_3['reg_month'] = pd.to_datetime(df2_3['reg_month']) sns.set_style('darkgrid') fig, ax = plt.subplots(figsize=(10, 6)) # 用整数索引作为x轴位置 x_indices = range(len(df2_3)) # 绘制第一个柱状图 ax1 = ax.bar( x=x_indices, height=df2_3['ses_users'], label='有会话的用户', linewidth=0, width=1, color='#3049BF' ) # 绘制堆叠的第二个柱状图 ax2 = ax.bar( x=x_indices, height=df2_3['no_ses_users'], bottom=df2_3['ses_users'], label='无会话的用户', linewidth=0, width=1, color='#BF9530' ) # 设置x轴刻度和日期标签,旋转45度避免重叠 ax.set_xticks(x_indices) ax.set_xticklabels(df2_3['reg_month'].dt.strftime('%Y-%m'), rotation=45) # 创建右侧Y轴 secax = ax.twinx() secax.set_ylim(min(df2_3['no_ses_users_ptc'])*0.5, max(df2_3['no_ses_users_ptc'])*1.1) # 在右侧轴绘制折线图,注意加逗号解包获取线条对象 ax3, = secax.plot( x=x_indices, y=df2_3['no_ses_users_ptc'], color='#E97800', label='无会话用户占比' ) # 合并两个轴的图例 main_handles, main_labels = ax.get_legend_handles_labels() sec_handles, sec_labels = secax.get_legend_handles_labels() ax.legend(main_handles + sec_handles, main_labels + sec_labels, loc='upper left') # 自动调整布局,防止标签被截断 plt.tight_layout() plt.show()
关键修改点
- 替换x轴为整数索引:彻底解决日期轴导致的柱子间隙问题,width=1让柱子完全贴合
- 统一图例:提取主、副轴的图例元素,合并后在主轴显示,避免两个独立图例
- 明确元素归属:用
ax.bar和secax.plot替代plt.bar/plt.plot,确保每个绘图元素属于正确的轴,避免图例提取错误 - 优化标签显示:旋转日期标签,用
tight_layout()避免布局混乱
内容的提问来源于stack exchange,提问作者John Doe
相关产品推荐
相关产品推荐

