有没有一种方法可以使色相seaborn条形图计数的总数达到每个色相条总数的100%?

时间:2019-09-02 09:26:12

标签: python-3.x matplotlib seaborn

我有一个不可思议的计数图,其中包括“色相参数”,这是该图的样子:

enter image description here

男性

男性总数= 240669,活跃男性总数= 130856,男性流失总数= 109813

M(有效)--- 130856/240669 = 54.4%和M(搅动)--- 109813/240669 = 45.6%

女性

女性总数= 198408,活跃女性总数= 111107,女性流失总数= 87301

所以F(有效)--- 111107/198408 = 56%和F(Churn)--- 87301/198408 = 44%

我希望每种性别的百分比总计为100%,而不是附图中给出的百分比。

这是我使用的代码:

plt.figure(figsize=(10,6))
colours = ['b','red']
ax = sns.countplot(df.GENDER,hue=df['Status'],order = 
df['GENDER'].value_counts().index,palette=colours)
plt.title("GENDER VS STATUS",fontsize=15)
plt.tight_layout()


plt.xticks(fontsize=14)
plt.yticks(fontsize=14)

total = float(len(df))
for p in ax.patches:
    height = p.get_height()
    ax.text(p.get_x()+p.get_width()/2.,
        height + 3,
        '{0:.1%}'.format(height/total),
        ha="center", fontsize=15)



print(df['GENDER'].value_counts(normalize=True))

2 个答案:

答案 0 :(得分:1)

在注释循环中,必须将高度除以M / F的总数。请记住,countplot会绘制按 hues 分组的补丁。就是说,补丁列表将是隔行扫描的M hue1 / F hue1 / M hue2 / F hue2,因此您可以将总数计算为“ [total M,total F,total M,total F]”并在其中循环遍历与您的补丁同时进行:

colours = ['b','red']
totals = df['GENDER'].value_counts()
n_hues = df['Status'].unique().size
ax = sns.countplot(df.GENDER,hue=df['Status'],order=totals.index,palette=colours)
plt.title("GENDER VS STATUS",fontsize=15)
plt.tight_layout()


plt.xticks(fontsize=14)
plt.yticks(fontsize=14)

temp_totals = totals.values.tolist()*n_hues
for p,t in zip(ax.patches,temp_totals):
    height = p.get_height()
    ax.text(p.get_x()+p.get_width()/2.,
        height + 3,
        '{0:.1%}'.format(height/t),
        ha="center", fontsize=15)

enter image description here

答案 1 :(得分:-1)

我总是发现分离数据聚合和绘图更为容易。因此,我建议首先计算所需的所有值,然后根据这些值绘制条形图。 (这里不需要Seaborn。)

import matplotlib.pyplot as plt
import pandas as pd

df = pd.DataFrame({"gender" : list("MMMMFFFFFF"),
                   "category" : list("BAABABBAAA")})

piv = df.groupby(["gender", "category"]).size().unstack("category")
grouped_perc = (piv.T / piv.sum(axis=0).values).T

ax = piv.plot.bar()
for bar, val in zip(ax.patches, grouped_perc.T.values.flat):
    ax.annotate('{0:.1%}'.format(val), 
                xy=(bar.get_x()+bar.get_width()/2., bar.get_height()),
                xytext=(0,5), textcoords="offset points", ha="center")

ax.margins(y=0.1)
plt.show()

enter image description here