如何绘制concern-infected主题下very与not_at_all合计百分比柱状图
问题背景
原始数据集
sample_size subject very not_at_all 0 2202 concern-economy 19.00 11.00 1 2202 concern-economy 26.00 7.00 2 1500 concern-infected 13.00 18.00 3 2200 concern-economy 23.00 9.00 4 1000 concern-infected 11.00 20.00 5 1500 concern-infected 11.00 22.00 9 1500 concern-infected 10.00 19.00 10 1500 concern-infected 10.00 20.00
字段说明
sample_size:受访总人数subject:访谈主题very:非常担忧的人群占比(单位:百分比)not_at_all:完全不担忧的人群占比(单位:百分比)
需求与现存问题
需要绘制concern-infected主题下,非常担忧、完全不担忧两个群体的合计百分比柱状图,现有代码如下:
infected = concern_polls[concern_polls["subject"] == "concern-infected"] infected.groupby('subject')[['very','not_at_all']].sum().plot.bar(rot=0)
当前问题:生成的图表将very和not_at_all列识别为整数,y轴没有展示为百分比格式。
解决方法
Pandas的plot接口默认不会自动将数值识别为百分比,你可以借助Matplotlib的PercentFormatter设置y轴格式,修改后代码如下:
import matplotlib.pyplot as plt from matplotlib.ticker import PercentFormatter import pandas as pd # 过滤目标主题数据 infected = concern_polls[concern_polls["subject"] == "concern-infected"] # 统计数值(注:直接对百分比求和逻辑有瑕疵,下文有修正方案) stat_data = infected.groupby('subject')[['very','not_at_all']].sum() # 绘图并配置百分比格式 ax = stat_data.plot.bar(rot=0) # 因为原始数据的数值本身就是百分比数值(比如13代表13%),所以xmax设为100 ax.yaxis.set_major_formatter(PercentFormatter(xmax=100)) # 可选配置:在柱子上方添加百分比标签 for container in ax.containers: ax.bar_label(container, fmt='%.1f%%') plt.show()
补充:合计百分比的正确计算逻辑
你当前直接对不同调查的百分比列求和的方式不准确,因为不同调查的样本量不同,需要按样本量加权计算整体的合计占比,正确代码如下:
# 计算每类人群的实际人数 infected['very_count'] = infected['sample_size'] * infected['very'] / 100 infected['not_at_all_count'] = infected['sample_size'] * infected['not_at_all'] / 100 # 计算整体加权占比 total_sample = infected['sample_size'].sum() total_very = infected['very_count'].sum() / total_sample * 100 total_not_at_all = infected['not_at_all_count'].sum() / total_sample * 100 # 构造绘图数据集 plot_data = pd.DataFrame({ '非常担忧': [total_very], '完全不担忧': [total_not_at_all] }, index=['concern-infected']) # 绘图逻辑和上文一致 ax = plot_data.plot.bar(rot=0) ax.yaxis.set_major_formatter(PercentFormatter(xmax=100)) for container in ax.containers: ax.bar_label(container, fmt='%.1f%%') plt.show()
内容的提问来源于stack exchange,提问作者Olaola
相关产品推荐
相关产品推荐

