如何使用Python seaborn绘制类人口金字塔的双面分组条形图
实现方案
你原有代码的核心问题有两个:一是缺少matplotlib.pyplot库导入,二是分组仅按性别划分,同一性别下的成年、幼年数据被seaborn默认的均值聚合逻辑合并,无法分开展示为左右两侧的条形。
以下是可直接运行的完整实现代码:
import pandas as pd import seaborn as sns import matplotlib.pyplot as plt import matplotlib.ticker as mticker # 构造测试数据 data = {'species': ['X', 'X', 'Y', 'Y', 'Z', 'Z', 'X', 'X', 'Y', 'Y', 'Z', 'Z'], 'sex': ['male', 'female', 'male', 'female', 'male', 'female', 'male', 'female', 'male', 'female', 'male', 'female'], 'mass (g)': [4000, 3500, 3800, 3200, 5500, 4900, 2500, 2100, 2400, 2000, 4200, 3800], 'age': ['adult', 'adult', 'adult', 'adult', 'adult', 'adult', 'juvenile', 'juvenile', 'juvenile', 'juvenile', 'juvenile', 'juvenile']} df = pd.DataFrame(data) # 幼年个体质量转为负数,用于展示在x轴左侧 df.loc[df.age.eq('juvenile'), 'mass (g)'] = df['mass (g)'].mul(-1) # 新增组合分组列,同时区分性别和年龄,避免数据被聚合 df['display_group'] = df['sex'] + '_' + df['age'] sns.set_theme(style="whitegrid") fig, ax = plt.subplots(figsize=(10,5)) # 自定义调色板:成年男蓝色、成年女橙色;幼年男浅红、幼年女深红 palette = { 'male_adult': '#1f77b4', 'female_adult': '#ff7f0e', 'male_juvenile': '#ff6b6b', 'female_juvenile': '#d62728' } # 绘制条形图 sns.barplot( data=df, x='mass (g)', y='species', hue='display_group', palette=palette, ci=False, orient='horizontal', dodge=True ) # 调整y轴位置到右侧 ax.yaxis.tick_right() ax.yaxis.set_label_position("right") # 调整x轴刻度,将左侧负数显示为正数,符合质量的实际含义 ax.xaxis.set_major_formatter(mticker.FuncFormatter(lambda x, pos: f"{abs(int(x))}")) # 调整图例标签,更易读 handles, labels = ax.get_legend_handles_labels() label_map = { 'male_adult': '成年雄性', 'female_adult': '成年雌性', 'male_juvenile': '幼年雄性', 'female_juvenile': '幼年雌性' } new_labels = [label_map[label] for label in labels] ax.legend(handles=handles, labels=new_labels, bbox_to_anchor=(1.15, 1), loc='upper left') # 设置轴标签 ax.set_xlabel('质量(g)') ax.set_ylabel('物种') plt.show()
关键实现说明
- 通过组合性别与年龄为独立分组,保证每一条数据对应一个独立的条形,不会被聚合
- 自定义调色板严格匹配需求:成年组按性别区分常规颜色,幼年组统一使用红色系展示在左侧
- x轴负刻度自动转换为正数展示,避免对质量数值产生误解
- 图例位置调整到图表外侧,不会遮挡条形内容
运行后即可得到你预期的双面金字塔图效果:
内容的提问来源于stack exchange,提问作者Medulla Oblongata
相关产品推荐
相关产品推荐

