如何用循环实现DataFrame多列堆叠百分比柱状图的绘制?
问题描述
已手动实现DataFrame的堆叠百分比柱状图,代码如下:
#creating a dataframe r = [0,1,2,3,4] raw_data = {'greenBars': [20, 1.5, 7, 10, 5], 'orangeBars': [5, 15, 5, 10, 15],'blueBars': [2, 15, 18, 5, 10]} df = pd.DataFrame(raw_data) # From raw value to percentage totals = list(df.sum(axis=1)) greenBars = [i / j * 100 for i,j in zip(df['greenBars'], totals)] orangeBars = [i / j * 100 for i,j in zip(df['orangeBars'], totals)] blueBars = [i / j * 100 for i,j in zip(df['blueBars'], totals)] # plot barWidth = 0.85 names = ('A','B','C','D','E') # Create green Bars plt.bar(df.index, greenBars, color='#b5ffb9', edgecolor='white', width=barWidth, label="group A") # Create orange Bars plt.bar(r, orangeBars, bottom=greenBars, color='#f9bc86', edgecolor='white', width=barWidth, label="group B") # Create blue Bars plt.bar(r, blueBars, bottom=[i+j for i,j in zip(greenBars, orangeBars)], color='#a3acff', edgecolor='white', width=barWidth, label="group C") # Custom x axis plt.xticks(r, names) plt.xlabel("group") # Add a legend plt.legend(loc='upper left', bbox_to_anchor=(1,1), ncol=1) # Show graphic plt.show()
但尝试用循环批量绘制多列DataFrame时,仅第一列柱状图完整显示,其余列显示不全,循环代码如下:
#Same df as above for column in df: placeholder = [i / j * 100 for i,j in zip(df[column], totals)] print(f'placeholder of {column}') print(placeholder) barWidth = 0.85 names = ('A','B','C','D','E') # Create green Bars plt.bar(df.index, placeholder, edgecolor='Black', width=barWidth, label = f"{column}")
修复方案
原循环代码的核心问题是未处理堆叠柱状图的bottom参数,每一列都从Y轴0位置开始绘制,后续列会和前面的列重叠,导致显示不全。同时重复定义无关变量也会降低效率,修复步骤如下:
- 提前计算每行总和、定义统一的图表参数(如barWidth、X轴名称),避免循环内重复执行
- 初始化一个全0的列表
bottom,用于记录每一行当前堆叠的总高度 - 循环遍历每一列时,将
bottom传入plt.bar()的bottom参数,让当前列从之前堆叠的高度开始绘制 - 绘制完成后,更新
bottom为当前堆叠高度加上列高度,供下一列使用 - 将X轴自定义、图例添加、图表显示等操作放在循环外,确保只执行一次
修复后的完整代码:
import pandas as pd import matplotlib.pyplot as plt # 创建DataFrame r = [0,1,2,3,4] raw_data = {'greenBars': [20, 1.5, 7, 10, 5], 'orangeBars': [5, 15, 5, 10, 15],'blueBars': [2, 15, 18, 5, 10]} df = pd.DataFrame(raw_data) # 计算每行总和,用于转换为百分比 totals = list(df.sum(axis=1)) # 统一图表参数 barWidth = 0.85 names = ('A','B','C','D','E') # 初始化堆叠底部,初始为0 bottom = [0] * len(df) for column in df: # 计算当前列的百分比 placeholder = [i / j * 100 for i,j in zip(df[column], totals)] # 绘制当前列,指定bottom参数实现堆叠 plt.bar(df.index, placeholder, edgecolor='Black', width=barWidth, label=column, bottom=bottom) # 更新堆叠底部,累加当前列高度 bottom = [current_bottom + p for current_bottom, p in zip(bottom, placeholder)] # 自定义X轴 plt.xticks(r, names) plt.xlabel("group") # 添加图例 plt.legend(loc='upper left', bbox_to_anchor=(1,1), ncol=1) # 显示图表 plt.show()
内容的提问来源于stack exchange,提问作者0k4y
相关产品推荐
相关产品推荐

