如何为每个类别创建展示欧美亚占比的水平堆叠条形图
创建等长水平堆叠条形图展示各区域占比
可以用matplotlib结合pandas实现需求,每个类别对应一个子图,堆叠条形展示欧洲、亚洲、美洲的占比,且所有条形总长度保持一致(因占比总和为1,所以x轴固定为0到1)。
完整代码示例
import pandas as pd import matplotlib.pyplot as plt # 构造给定的DataFrame data = { 'type': ['cat1', 'cat2', 'cat3', 'cat4', 'cat5', 'cat6', 'cat7', 'cat8', 'cat9'], 'eur_d': [0.58, 0.50, 0.50, 0.42, 0.42, 0.60, 0.26, 0.54, 0.46], 'asia_d': [0.30, 0.29, 0.30, 0.31, 0.37, 0.21, 0.50, 0.17, 0.25], 'amer_d': [0.12, 0.21, 0.20, 0.27, 0.20, 0.19, 0.24, 0.30, 0.29] } df = pd.DataFrame(data) # 定义各区域对应的颜色 colors = ['#1f77b4', '#ff7f0e', '#2ca02c'] # 欧洲蓝、亚洲橙、美洲绿 regions = ['eur_d', 'asia_d', 'amer_d'] region_labels = ['欧洲', '亚洲', '美洲'] # 创建3行3列的子图布局,调整子图间距 fig, axes = plt.subplots(nrows=3, ncols=3, figsize=(12, 8)) axes = axes.flatten() # 将二维轴数组转为一维,方便循环 # 循环每个类别绘制堆叠水平条形图 for idx, ax in enumerate(axes): row = df.iloc[idx] # 堆叠绘制水平条形,起始位置依次累加前一个区域的占比 left = 0 for reg, color, label in zip(regions, colors, region_labels): ax.barh(y=0, width=row[reg], left=left, color=color, label=label) left += row[reg] # 设置子图标题为类别名称 ax.set_title(row['type']) # 隐藏y轴(因每个子图只有一个y项,无需显示) ax.set_yticks([]) # 固定x轴范围,确保所有条形总长度一致 ax.set_xlim(0, 1) # 添加x轴标签(占比) ax.set_xlabel('占比') # 在最后一个子图添加图例,调整位置避免遮挡 axes[-1].legend(loc='upper right', bbox_to_anchor=(1.3, 0.5)) # 调整整体布局,避免标题、标签重叠 plt.tight_layout() plt.show()
代码说明
- 先构造目标DataFrame,定义各区域的展示颜色和标签;
- 使用
subplots创建3×3的子图网格,扁平化后逐个处理每个类别; - 对每个子图,通过循环堆叠绘制水平条形,
left参数控制每个条形的起始位置,实现堆叠效果; - 固定x轴范围为0到1,保证所有子图的条形总长度完全一致;
- 隐藏y轴(每个子图仅展示单个类别的占比,y轴无实际意义),添加标题和x轴标签,最后调整布局并展示。
内容的提问来源于stack exchange,提问作者Olive
相关产品推荐
相关产品推荐

