【问题标题】:Python: Plotting percentage in seaborn bar plotPython:在seaborn条形图中绘制百分比
【发布时间】:2016-06-12 02:13:11
【问题描述】:

对于数据框

import pandas as pd
df=pd.DataFrame({'group':list("AADABCBCCCD"),'Values':[1,0,1,0,1,0,0,1,0,1,0]})

我正在尝试绘制一个条形图,显示 A, B, C, D 取零(或一)的次数百分比。

我有一个可行的方法,但我认为必须有更直接的方法

tempdf=df.groupby(['group','Values']).Values.count().unstack().fillna(0)
tempdf['total']=df['group'].value_counts()
tempdf['percent']=tempdf[0]/tempdf['total']*100

tempdf.reset_index(inplace=True)
print tempdf

sns.barplot(x='group',y='percent',data=tempdf)

如果它只是绘制平均值,我可以简单地在 df 数据帧上做 sns.barplot 而不是 tempdf。如果我对绘制百分比感兴趣,我不确定如何优雅地做到这一点。

谢谢,

【问题讨论】:

  • 有一种方法可以直接使用 Dexplot 库来做到这一点。见my answer below

标签: python pandas bar-chart seaborn


【解决方案1】:

您可以将 Pandas 与 seaborn 结合使用以简化此操作:

import pandas as pd
import seaborn as sns

df = sns.load_dataset("tips")
x, y, hue = "day", "proportion", "sex"
hue_order = ["Male", "Female"]

(df[x]
 .groupby(df[hue])
 .value_counts(normalize=True)
 .rename(y)
 .reset_index()
 .pipe((sns.barplot, "data"), x=x, y=y, hue=hue))

【讨论】:

    【解决方案2】:

    你可以在sns.barplotestimator中使用你自己的函数,从docs开始:

    estimator:映射向量的可调用 -> 标量,可选
    在每个分类箱内估计的统计函数。

    对于您的情况,您可以将函数定义为 lambda:

    sns.barplot(x='group', y='Values', data=df, estimator=lambda x: sum(x==0)*100.0/len(x))
    

    【讨论】:

    • 谢谢@anton。这几乎可以完美地工作。除法没有给出浮点值但包括1.0 工作sns.barplot(x='group', y='Values', data=df, estimator=lambda x: sum(x==0)*1.0/len(x))
    • @PagMax 我正在使用 python 3.x 所以我没有那个,如果你使用 python 2,你应该像你一样添加 1.0 或者如果你需要 percentage你可以乘以100.0
    • 谢谢,我理解其中的区别。是的,我使用的是 python 2.x,是的,乘以 100.0 也可以,但这必须在除法操作之前,如 sum(x==0)*100.0/len(x) 而不是 sum(x==0)/len(x)*100.0。无论如何,问题已解决,非常感谢您的帮助。
    【解决方案3】:

    您可以按照以下步骤操作,以便在绘图中的条形顶部查看计数和百分比。检查下面的示例输出

    with_hue 如果您的绘图中有“hue”参数,则函数将在条形图上绘制百分比。以实际图、特征、特征中的Number_of_categories、hue_categories(hue特征中的类别数)为参数。

    without_hue 函数将在条形图上绘制百分比,如果你有一个正常的绘图。它以实际的图形和特征作为参数。

    def with_hue(plot, feature, Number_of_categories, hue_categories):
        a = [p.get_height() for p in plot.patches]
        patch = [p for p in plot.patches]
        for i in range(Number_of_categories):
            total = feature.value_counts().values[i]
            for j in range(hue_categories):
                percentage = '{:.1f}%'.format(100 * a[(j*Number_of_categories + i)]/total)
                x = patch[(j*Number_of_categories + i)].get_x() + patch[(j*Number_of_categories + i)].get_width() / 2 - 0.15
                y = patch[(j*Number_of_categories + i)].get_y() + patch[(j*Number_of_categories + i)].get_height() 
                ax.annotate(percentage, (x, y), size = 12)
        plt.show()
    
    def without_hue(plot, feature):
        total = len(feature)
        for p in ax.patches:
            percentage = '{:.1f}%'.format(100 * p.get_height()/total)
            x = p.get_x() + p.get_width() / 2 - 0.05
            y = p.get_y() + p.get_height()
            ax.annotate(percentage, (x, y), size = 12)
        plt.show()
    

    【讨论】:

      【解决方案4】:

      您可以使用library Dexplot,它能够返回分类变量的相对频率。它具有与 Seaborn 类似的 API。将您想要获取相对频率的列传递给count 函数。如果您想将其细分为另一列,请使用split 参数。以下返回原始计数。

      import dexplot as dxp
      dxp.count('group', data=df, split='Values')
      

      要获取相对频率,请将normalize 参数设置为您要标准化的列。使用True 对总计数进行归一化。

      dxp.count('group', data=df, split='Values', normalize='group')
      

      'Values' 列进行标准化将生成下图,其中所有“0”条的总数为1。

      dxp.count('group', data=df, split='Values', normalize='Values')
      

      【讨论】:

        猜你喜欢
        • 2021-12-22
        • 1970-01-01
        • 1970-01-01
        • 2019-09-27
        • 1970-01-01
        • 1970-01-01
        • 2016-07-09
        • 1970-01-01
        • 2019-06-08
        相关资源
        最近更新 更多