如何针对未知数量的financing_type类别绘制Matplotlib堆叠柱状图?
通用实现按未知类别列求和的堆叠柱状图
原始数据
import pandas as pd df = pd.DataFrame({ 'Plan': [40, 50, 60, 25], 'Fact': [10, 20, 30, 15], 'financing_type': ['type_1', 'type_2', 'type_1', 'type_3'] })
需求
按financing_type分组对Plan和Fact列求和,绘制堆叠柱状图(每个Plan/Fact柱子由不同类型的求和值堆叠而成)。
手动实现代码(仅适用于已知类别数量)
import matplotlib.pyplot as plt df_type_1 = df[df['financing_type'] == 'type_1'] df_type_2 = df[df['financing_type'] == 'type_2'] df_type_3 = df[df['financing_type'] == 'type_3'] plt.bar(['Plan', 'Fact'], [df_type_1['Plan'].sum(), df_type_1['Fact'].sum()], color='blue', label='type_1') plt.bar( ['Plan', 'Fact'], [df_type_2['Plan'].sum(), df_type_2['Fact'].sum()], bottom=[df_type_1['Plan'].sum(), df_type_1['Fact'].sum()], color='red', label='type_2', ) plt.bar( ['Plan', 'Fact'], [df_type_3['Plan'].sum(), df_type_3['Fact'].sum()], bottom=[df_type_1['Plan'].sum() + df_type_2['Plan'].sum(), df_type_1['Fact'].sum() + df_type_2['Fact'].sum()], color='green', label='type_3', ) plt.legend() plt.show()
通用实现方案(适配未知类别数量)
方法1:利用Pandas内置绘图(最简洁)
通过groupby分组求和后转置数据,直接调用Pandas的堆叠柱状图接口,无需手动处理堆叠逻辑:
import matplotlib.pyplot as plt # 分组求和并转置,让索引为Plan/Fact,列为各融资类型 sum_df = df.groupby('financing_type')[['Plan', 'Fact']].sum().T # 绘制堆叠柱状图 sum_df.plot(kind='bar', stacked=True, colormap='viridis') plt.legend(title='financing_type') plt.title('Plan/Fact 按融资类型堆叠求和') plt.show()
方法2:手动Matplotlib循环(自定义性更强)
如果需要灵活控制颜色、标签等细节,可通过循环遍历所有类别,维护bottom参数实现堆叠:
import matplotlib.pyplot as plt # 获取所有不重复的融资类型 types = df['financing_type'].unique() x_labels = ['Plan', 'Fact'] # 初始化堆叠底部为0 bottom = [0] * len(x_labels) # 用颜色映射生成动态颜色(避免手动指定颜色) colors = plt.cm.viridis([i/len(types) for i in range(len(types))]) for idx, t in enumerate(types): # 获取当前类型的求和值 type_sum = df[df['financing_type'] == t][['Plan', 'Fact']].sum().values # 绘制当前层柱状图 plt.bar(x_labels, type_sum, bottom=bottom, color=colors[idx], label=t) # 更新底部值,为下一层堆叠做准备 bottom = [bottom[i] + type_sum[i] for i in range(len(bottom))] plt.legend(title='financing_type') plt.title('Plan/Fact 按融资类型堆叠求和') plt.show()
内容的提问来源于stack exchange,提问作者Duncan
相关产品推荐
相关产品推荐

