如何为Seaborn分组条形图添加另一列的数值标注?
问题
制作展示各时间段胜诉率的分组条形图,并在条形图上标注对应时间段的胜诉案件数量。现有代码能生成胜诉率条形图,但标注的是胜诉率数值;尝试过的方法要么新增额外条形,要么标注内容不对,需要简洁实现方式。
简洁解决方案
核心思路是保留原始数据中的案件数量列,在绘制完胜诉率条形图后,按条形的顺序匹配对应的案件数量进行标注,无需修改原有的melt逻辑。
修改后的完整代码:
import pandas as pd import numpy as np import seaborn as sns import matplotlib.pyplot as plt # 原始数据 df_original = pd.DataFrame({ 'years': ['1994-1998','1999-2003','2004-2008','2009-2013','2013-2017','2018-2022'], 'Starfish number of cases': [10,8,31,12,2,3], 'Starfish percent of wins': [0,0.25,0.225806451612903,0.416666666666666,1,0], 'Jellyfish number of cases':[597,429,183,238,510,595], 'Jellyfish percent of wins':[0.362646566164154,0.273892773892773,0.423497267759562,0.478991596638655,0.405882352941176,0.408403361344537], }) # 仅melt胜诉率列,用于绘制条形图 df_melt = pd.melt(df_original, id_vars=['years'], value_vars=['Starfish percent of wins', 'Jellyfish percent of wins']) sns.set_theme(style="whitegrid") f, ax = plt.subplots(figsize=(30, 15)) # 绘制分组条形图 sns.barplot(x="years", y="value", hue='variable', data=df_melt) # 整理案件数量列表,顺序与条形图的patch顺序一致 case_counts = [] for _, row in df_original.iterrows(): case_counts.append(row['Starfish number of cases']) case_counts.append(row['Jellyfish number of cases']) # 逐个标注案件数量 for p, count in zip(ax.patches, case_counts): ax.annotate(f'案件数: {count}', (p.get_x() + p.get_width()/2, p.get_height()), ha='center', va='bottom', fontsize=12) plt.show()
代码解释
- 保留原始数据:将原始DataFrame命名为
df_original,避免melt操作覆盖原始的案件数量数据。 - 匹配条形顺序:分组条形图的每个时间段会先绘制
Starfish的条形,再绘制Jellyfish的条形,因此按年份遍历原始数据,依次添加两类的案件数量到case_counts列表,保证顺序完全匹配。 - 精准标注:使用
zip将每个条形(ax.patches)和对应的案件数量配对,在条形顶部居中标注案件数,位置和样式更清晰。
内容的提问来源于stack exchange,提问作者oymonk
相关产品推荐
相关产品推荐

