基于DataFrame逐步构建非堆叠柱状图失败,求解决方案
问题:循环绘制非堆叠多系列柱状图失败
我尝试用Pandas、matplotlib和Jupyter构建柱状图,想要同一索引值的多个系列依次排列而非堆叠。写了如下代码:
d = { "shop": [ "London", "Berlin", "Paris" ], "sales-2020": [ 1000, 2344, 1233 ], "sales-2021": [ 355, 4003, 2344 ], "sales-2022": [ 2344, 2949, 3443 ] } colors = { "2020": "Blue", "2021": "Green", "2022": "Red" } df = pd.DataFrame ( d, index = d [ "shop" ] ) ax = None for yk in [ 2020, 2021, 2022 ]: yk = str ( yk ) ax = df.plot.bar ( y = "sales-" + yk, label = yk, color = colors [ yk ], stacked = False, ax = ax )
但输出有问题:系列始终是堆叠状态,而且第一个系列没显示成柱状图。
注:这是复杂场景的简化,我有9个系列,必须通过循环逐个添加到图表,不能一次性构建;也不需要做透视表,数据已经分组好。
解决方案
问题出在循环调用df.plot.bar()时,每次仅传入单个列,Pandas会默认将这些系列叠加在同一组柱子上,而非并排显示。要实现并排效果,需要手动调整每个系列柱子的位置和宽度。
修改后的代码如下:
import pandas as pd import matplotlib.pyplot as plt d = { "shop": [ "London", "Berlin", "Paris" ], "sales-2020": [ 1000, 2344, 1233 ], "sales-2021": [ 355, 4003, 2344 ], "sales-2022": [ 2344, 2949, 3443 ] } colors = { "2020": "Blue", "2021": "Green", "2022": "Red" } years = ["2020", "2021", "2022"] n_series = len(years) bar_width = 0.25 # 根据系列数量调整柱子宽度 df = pd.DataFrame(d, index=d["shop"]) x = range(len(df.index)) # 获取x轴位置索引 fig, ax = plt.subplots() for i, year in enumerate(years): # 计算每个系列的x轴偏移量,实现并排效果 ax.bar([pos + i*bar_width for pos in x], df[f"sales-{year}"], width=bar_width, label=year, color=colors[year]) # 调整x轴刻度位置,使其对齐每组柱子的中间 ax.set_xticks([pos + bar_width*(n_series-1)/2 for pos in x]) ax.set_xticklabels(df.index) ax.set_xlabel("Shop") ax.set_ylabel("Sales") ax.set_title("Sales by Year and Shop") ax.legend() plt.show()
关键调整说明
- 手动计算每个系列的x轴位置偏移,确保同一索引下的柱子并排排列
- 统一设置柱子宽度,避免重叠
- 最后调整x轴刻度位置,使其与每组柱子的中心对齐
内容的提问来源于stack exchange,提问作者zakmck
相关产品推荐
相关产品推荐

