如何让Pandas绘图中不同宽度的重叠条形图完美居中?
解决Pandas条形图twiny时不同宽度条形的居中重叠问题
这个问题我之前也碰到过!默认情况下用twiny()创建双x轴后,两组条形因为bar函数默认的对齐方式是左边缘(align='edge'),当宽度不同时,中心自然就错开了,确实看着很别扭。不过有两个简单的方法可以解决这个问题:
方法一:使用align='center'参数(推荐)
这是最直接的解决方案,只需要在绘制两组条形时都指定align='center',让条形的x坐标对应分类的中心位置,不管宽度怎么调整,两组条形的中心都会完美重合。
示例代码:
import pandas as pd import matplotlib.pyplot as plt # 模拟你的数据 df_group1 = pd.DataFrame({'category': ['cat1', 'cat2'], 'value': [3, 5]}) df_group2 = pd.DataFrame({'category': ['cat1', 'cat2'], 'value': [4, 2]}) fig, ax_bottom = plt.subplots(figsize=(8, 5)) # 绘制底部x轴的条形,宽度0.4,居中对齐 bars_bottom = ax_bottom.bar( df_group1['category'], df_group1['value'], width=0.4, color='black', align='center', label='Group 1' ) # 创建顶部x轴 ax_top = ax_bottom.twiny() # 绘制顶部x轴的条形,宽度0.2,同样居中对齐 bars_top = ax_top.bar( df_group2['category'], df_group2['value'], width=0.2, color='#ff4444', align='center', label='Group 2' ) # 添加图例和标签,让图表更清晰 ax_bottom.set_ylabel('Group 1 Value') ax_top.set_ylabel('Group 2 Value') ax_bottom.legend(loc='upper left') ax_top.legend(loc='upper right') plt.tight_layout() plt.show()
这样调整后,不管你把两组条形的宽度改成多少,它们都会始终以分类中心为基准重叠,完美对齐。
方法二:手动计算中心位置(适合已用默认对齐的场景)
如果你已经用了默认的align='edge',不想修改这个设置,可以手动计算第一组条形的中心位置,然后调整第二组条形的x坐标,让它的中心和第一组重合:
import pandas as pd import matplotlib.pyplot as plt df_group1 = pd.DataFrame({'category': ['cat1', 'cat2'], 'value': [3, 5]}) df_group2 = pd.DataFrame({'category': ['cat1', 'cat2'], 'value': [4, 2]}) fig, ax_bottom = plt.subplots(figsize=(8, 5)) # 绘制底部条形(默认左对齐) bars_bottom = ax_bottom.bar( df_group1['category'], df_group1['value'], width=0.4, color='black', label='Group 1' ) # 计算底部条形的中心位置 bar_centers = [bar.get_x() + bar.get_width()/2 for bar in bars_bottom] # 创建顶部x轴 ax_top = ax_bottom.twiny() # 绘制顶部条形,x坐标设置为底部条形的中心减去自身宽度的一半 bars_top = ax_top.bar( [center - 0.2/2 for center in bar_centers], # 0.2是顶部条形的宽度 df_group2['value'], width=0.2, color='#ff4444', label='Group 2' ) # 同步顶部x轴的刻度位置和标签 ax_top.set_xticks(bar_centers) ax_top.set_xticklabels(df_group2['category']) # 添加图例和标签 ax_bottom.set_ylabel('Group 1 Value') ax_top.set_ylabel('Group 2 Value') ax_bottom.legend(loc='upper left') ax_top.legend(loc='upper right') plt.tight_layout() plt.show()
这个方法的核心是通过bar.get_x()获取条形左边缘位置,加上宽度的一半得到中心,再让顶部条形的左边缘位置等于中心减去自身宽度的一半,这样两者的中心就完全重合了。
内容的提问来源于stack exchange,提问作者BoroBorooooooooooooooooooooooo




