如何创建带标注分位线段的年度数据可视化图表
问题描述
我想制作一种类似堆叠柱状图的图表(不确定准确名称),手绘了2016和2017年的示例图(未附上)。现有生成DataFrame的代码如下,但当前代码生成的是堆叠柱状图,并非我需要的效果。我需要针对每个年份,在对应位置用带标注的水平线段展示各百分位数的数值,请问如何实现?这是否属于修改版Stacked Bar Chart?
import pandas as pd import matplotlib.pyplot as plt import seaborn as sns data = [[2016.0, 0.4862, 0.4115, 0.3905, 0.3483, 0.1196], [2017.0, 0.4471, 0.4096, 0.3725, 0.2866, 0.1387], [2018.0, 0.4748, 0.4016, 0.3381, 0.2905, 0.2012], [2019.0, 0.4705, 0.4247, 0.3857, 0.3333, 0.2457], [2020.0, 0.4755, 0.4196, 0.3971, 0.3825, 0.2965]] cols = ['attribute_time', '100-81 percentile', '80-61 percentile', '60-41 percentile', '40-21 percentile', '20-0 percentile'] df = pd.DataFrame(data, columns=cols) #set seaborn plotting aesthetics sns.set(style='white') #create stacked bar chart df.set_index('attribute_time').plot(kind='bar', stacked=True)
解决方案
图表类型说明
这种图表不属于修改版堆叠柱状图:堆叠柱状图的核心是数值累加堆叠,用面积占比展示总和与细分项的关系;而你的需求是在每个年份的垂直位置上,独立标记多个百分位数的数值长度,更适合称为类别式多水平标记图,也可看作平行坐标图针对类别轴的简化形式。
实现代码
import pandas as pd import matplotlib.pyplot as plt import seaborn as sns # 初始化数据 data = [[2016.0, 0.4862, 0.4115, 0.3905, 0.3483, 0.1196], [2017.0, 0.4471, 0.4096, 0.3725, 0.2866, 0.1387], [2018.0, 0.4748, 0.4016, 0.3381, 0.2905, 0.2012], [2019.0, 0.4705, 0.4247, 0.3857, 0.3333, 0.2457], [2020.0, 0.4755, 0.4196, 0.3971, 0.3825, 0.2965]] cols = ['attribute_time', '100-81 percentile', '80-61 percentile', '60-41 percentile', '40-21 percentile', '20-0 percentile'] df = pd.DataFrame(data, columns=cols) # 设置绘图风格 sns.set(style='whitegrid') fig, ax = plt.subplots(figsize=(10, 6)) # 获取年份的垂直位置(y轴坐标) year_positions = range(len(df['attribute_time'])) years = df['attribute_time'].astype(int) # 遍历每个百分位数列,绘制水平线段并添加标注 for col_idx, col in enumerate(cols[1:]): values = df[col] # 绘制水平线段:y轴对应年份位置,x从0延伸到百分位数数值 ax.hlines(y=year_positions, xmin=0, xmax=values, color=f'C{col_idx}', linewidth=3, label=col) # 在线段末端添加数值标注 for y, val in zip(year_positions, values): ax.text(val + 0.01, y, f'{val:.4f}', va='center', fontsize=9) # 配置轴标签与刻度 ax.set_yticks(year_positions) ax.set_yticklabels(years) ax.set_xlabel('Percentile Value') ax.set_ylabel('Year') ax.set_title('Percentile Values by Year') # 调整图例位置避免遮挡 ax.legend(bbox_to_anchor=(1.05, 1), loc='upper left') # 优化布局 plt.tight_layout() plt.show()
代码关键说明
- 使用
ax.hlines()绘制水平线段,每个百分位数用不同颜色区分,线段长度直接对应该年份的百分位数数值 - 通过
ax.text()在每个线段末端添加数值标注,确保数据可读性 - 将y轴设置为年份类别,每个年份对应固定垂直位置,清晰区分不同年份的数据
- 调整图例位置到图表外侧,避免遮挡核心内容
内容的提问来源于stack exchange,提问作者BrianBeing
相关产品推荐
相关产品推荐

