Matplotlib / SeabornCountplot-未考虑色相的百分比

问题描述

我按照以下指示创建了一个计数图:https://stackoverflow.com/a/33259038

ncount = len(bod)

plt.figure(figsize=(14,6))
ax = sns.countplot(x="Preparedness_Q2",hue='country_group',data=bod,palette='inferno',order=["Not at all","Prepared only in some aspects","Prepared enough",'Fully prepared','No Answer']) 
plt.title('Preparedness for the pandemic',pad=20,fontsize=20)
plt.xlabel(None)
plt.ylabel('Number of Observations',labelpad=15)

# Make twin axis
ax2=ax.twinx()
ax2.axes.yaxis.set_visible(False)

for p in ax.patches:
    x=p.get_bBox().get_points()[:,0]
    y=p.get_bBox().get_points()[1,1]
    ax.annotate('{:.1f}%'.format(100.*y/ncount),(x.mean(),y),ha='center',va='bottom') 

输出看起来像这样:

enter image description here

我无法通过“色相”来区分百分比,它目前提供的百分比是总数的一部分(加上“其他”和“西班牙”的所有观察结果)。有没有办法提供按组划分的百分比?通过这个答案https://stackoverflow.com/a/59433700,我发现您可以根据每对列进行分隔,但不能根据组进行分隔。

当前是“​​ ncount”计算“总计”。我做了一个非常丑陋的更改就能得到正确的百分比,这是代码

for num,p in enumerate(ax.patches):
    x=p.get_bBox().get_points()[:,1]
    if num <= (len(ax.patches)/2)-1:
        ax.annotate('{:.1f}%'.format(100.*y/other),va='bottom') 
    else:
        ax.annotate('{:.1f}%'.format(100.*y/spain),va='bottom') 

在此,“其他”和“西班牙”是每组观察值的总数。但是我的问题是,计数图优先考虑“计数”而不是“百分比”。因此输出完全关闭,请参见以下结果:

enter image description here

有人对如何解决这个问题有建议吗?预先感谢!

解决方法

发布这个问题几分钟后,我感到有点愚蠢,我发现这个github答案https://github.com/mwaskom/seaborn/issues/1027#issuecomment-360866896包含解决方案...

出于完整性考虑,这是我使用的代码:

x,hue = "Preparedness_Q2","country_group"
hue_order = ["Not at all","Prepared only in some aspects","Prepared enough",'Fully prepared','No Answer']

prop_df = (bod[x].groupby(bod[hue]).value_counts(normalize=True).rename(y).reset_index())

plt.figure(figsize=(15,6))
ax = sns.barplot(x=x,y=y,hue=hue,data=prop_df,order=hue_order)

plt.title('Preparedness for the pandemic',pad=20,fontsize=20)
plt.xlabel(None)
plt.ylabel('Frequencies [%]',labelpad=15)

for p in ax.patches:
    x=p.get_bbox().get_points()[:,0]
    y=p.get_bbox().get_points()[1,1]
    ax.annotate('{:.1f}%'.format(100.*y),(x.mean(),y),ha='center',va='bottom') # set the alignment of the text
    
# Change legend title
legend = ax.legend(loc='upper left')
legend.texts[0].set_text("Other countries")

plt.show()

enter image description here

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...