使用matplotlib/seaborn绘制分国家的年度份额堆叠柱状图
Pandas+Matplotlib绘制符合要求的堆叠柱状图
你的数据集本身每个年份下的share加和已经是1,不需要额外做归一化计算,直接将数据透视为「年份为行、国家为列」的结构后,调用matplotlib的柱状图接口开启堆叠模式即可,完整可运行代码如下:
import pandas as pd import matplotlib.pyplot as plt # 构造原始数据集 data = {'country': ['US', 'DE', 'IT', 'US', 'DE', 'IT', 'US', 'DE', 'IT'], 'year': [2000,2000,2000,2001,2001,2001,2002,2002,2002], 'share': [0.5, 0.3, 0.2, 0.6,0.1,0.3,0.4,0.2,0.4]} df = pd.DataFrame(data) # 透视转换为堆叠柱状图要求的输入格式 pivot_data = df.pivot(index='year', columns='country', values='share') # 初始化画布绘图 fig, ax = plt.subplots(figsize=(7, 4)) pivot_data.plot( kind='bar', stacked=True, ax=ax, edgecolor='white', # 给不同国家的块加白边区分更清晰 width=0.6 # 调整柱宽更美观 ) # 基础配置 ax.set_xlabel('年份') ax.set_ylabel('份额') ax.set_xticklabels(pivot_data.index, rotation=0) # 年份标签横向显示,不用倾斜 ax.set_ylim(0, 1.05) # 顶部留少量边距 ax.legend(title='国家', bbox_to_anchor=(1.02, 1), loc='upper left') # 图例放图外不遮挡内容 # 可选:给每个色块加中心数值标签 for container in ax.containers: ax.bar_label(container, label_type='center', fmt='%.1f') plt.tight_layout() # 自动调整布局避免标签截断 plt.show()
对应要求的实现逻辑
- X轴:直接使用透视表的行索引,也就是
year字段的唯一值 - Y轴:直接映射
share字段数值,因为每年份份额总和固定为1,三个年份的柱体总高度完全一致 - 颜色区分:绘图时会自动给不同国家(也就是透视表的不同列)分配差异化的填充色,你也可以传入
color参数自定义配色,比如color=['#e41a1c', '#377eb8', '#4daf4a'] - 总高度一致:原始数据已经满足每年份
share和为1的要求,如果后续换数据集出现总和不为1的情况,只需要在透视前加一行df['share'] = df.groupby('year')['share'].transform(lambda x: x/x.sum())做归一化即可。
内容的提问来源于stack exchange,提问作者Pineapple P
相关产品推荐
相关产品推荐

