如何用Matplotlib在同一张图中并列绘制Pandas多组柱状图?
解决Matplotlib并列柱状图重叠问题
你的问题出在两次调用ax.bar时使用了相同的分类x轴标签——Matplotlib会把每个分类标签映射到同一个坐标点,导致第二组柱子直接叠在第一组上面,看起来像是堆叠效果。要实现并列柱状图,你需要手动给两组柱子设置错开的x轴位置,具体修改方案如下:
修改后的完整代码
import pandas as pd import matplotlib.pyplot as plt import matplotlib.ticker as ticker import numpy as np # 初始化你的DataFrame df_test1 = pd.DataFrame( [['<18', 80841], ['18-24', 334725], ['25-44', 698261], ['45-64', 273087], ['65+', 15035]], columns = ['age_group', 'total_arrests'] ) df_test2 = pd.DataFrame( [['<18', 33979], ['18-24', 106857], ['25-44', 219324], ['45-64', 80647], ['65+', 4211]], columns = ['age_group','total_arrests'] ) fig, ax = plt.subplots() width = 0.35 # 设置柱子宽度,控制两组柱子的间距 x = np.arange(len(df_test1.age_group)) # 生成数值型x轴位置,方便偏移 # 绘制两组并列柱子 ax.bar(x - width/2, df_test1.total_arrests, width=width, color='seagreen', label='All Arrests') ax.bar(x + width/2, df_test2.total_arrests, width=width, color='lightgreen', label='Felony Arrests') # 设置轴标签和标题 ax.set_xlabel('Age Group') ax.set_ylabel('Number of Arrests') ax.set_title('Arrests vs. Felony Arrests by Age Group') # 设置x轴刻度为年龄组,放在两组柱子中间 ax.set_xticks(x) ax.set_xticklabels(df_test1.age_group) # y轴千分位格式化 ax.yaxis.set_major_formatter(ticker.FuncFormatter(lambda y,p: format(int(y), ','))) # 添加柱子顶部的数值注释 for i, j in enumerate(df_test1.total_arrests): ax.annotate(format(j, ','), xy=(x[i] - width/2, j), ha='center') for i, j in enumerate(df_test2.total_arrests): ax.annotate(format(j, ','), xy=(x[i] + width/2, j), ha='center') # 添加图例(直接用bar的label参数,比手动传列表更规范) ax.legend() plt.show()
关键改动说明
- 数值型x轴位置:用
np.arange生成0、1、2...这样的数值坐标,替代原来的分类标签,方便对两组柱子进行位置偏移。 - 柱子位置偏移:第一组柱子向左偏移
width/2,第二组向右偏移width/2,这样两组柱子就会并列排列在刻度两侧。 - 刻度位置调整:把x轴刻度设置在两组柱子的中间位置,再替换为年龄组标签,保证视觉上的合理性。
- 注释位置修正:注释的x坐标要对应每组柱子的实际位置,同时设置
ha='center'让文字居中显示在柱子顶部。 - 图例优化:直接在
ax.bar中指定label参数,再调用ax.legend(),比手动传图例列表更不易出错(顺便修正了你原来代码里的拼写错误Arressts)。
这样修改后,就能得到你想要的并列柱状图效果啦。
内容的提问来源于stack exchange,提问作者IamWarmduscher
相关产品推荐
相关产品推荐

