【问题标题】:Plot groupby percentage dataframe绘制分组百分比数据框
【发布时间】:2021-06-26 22:43:56
【问题描述】:

我没有找到我想做的事情的完整答案:

我有一个数据框。我想按用户及其对调查的答案进行分组,将他们所有的好答案/他们的答案总数相加,以百分比显示并绘制结果。

我有一个答案列,其中包含:1,0 或 -1。我想过滤它以排除-1。

这是我到目前为止所做的:

df_sample.groupby('user').filter(lambda x : x['answer'].mean() >-1)

或:

a = df_sample.loc[df_sample['answer']!=-1,['user','answer']]
b = a.groupby(['user','answer']).agg({'answer' : 'sum'})

看看它是不完整的。感谢您提出的任何建议。

【问题讨论】:

  • 获得比例变化 .agg({'answer' : 'sum'}).agg({'answer' : 'mean'})。如果我了解您在寻找什么。

标签: python pandas dataframe matplotlib


【解决方案1】:

让我们尝试一些示例数据:

import numpy as np
import pandas as pd
from matplotlib import pyplot as plt

np.random.seed(5)
n = 100
df = pd.DataFrame({'user': np.random.choice(list("ABCD"), size=n),
                   'answer': np.random.choice([1, 0, -1], size=n)})

df.head():

  user  answer
0    D       1
1    C       0
2    D      -1
3    B       1
4    C       1

选项 1

过滤掉-1 值并使用命名聚合来获得“好答案”和“总答案”:

plot_df = df[df['answer'].ne(-1)].groupby('user').aggregate(
    good_answer=('answer', 'sum'),
    total_answer=('answer', 'size')
)

plot_df:

      good_answer  total_answer
user                           
A               9            15
B              11            20
C              15            19
D               7            14

使用除法和乘法得到百分比:

plot_df['pct'] = (plot_df['good_answer'] / plot_df['total_answer'] * 100)

plot_df:

      good_answer  total_answer        pct
user                                      
A               9            15  60.000000
B              11            20  55.000000
C              15            19  78.947368
D               7            14  50.000000

那么这可以用DataFrame.plot绘制:

ax = plot_df.plot(
    y='pct', kind='bar', rot=0,
    title='Percentage of Good Answers',
    ylim=[0, 100],
    label='Percent Good'
)

# Add Labels on Top of Bars
for container in ax.containers:
    ax.bar_label(container, fmt='%.2f%%')

plt.show()

选项2

如果只是需要百分比,groupby mean 可用于在过滤掉-1s 后直接得到结果图:

plot_df = df[df['answer'].ne(-1)].groupby('user')['answer'].mean().mul(100)

ax = plot_df.plot(
    kind='bar', rot=0,
    title='Percentage of Good Answers',
    ylim=[0, 100],
    label='Percent Good'
)
# Add Labels on Top of Bars
for container in ax.containers:
    ax.bar_label(container, fmt='%.2f%%')

plt.show()

plot_df:

         answer
user           
A     60.000000
B     55.000000
C     78.947368
D     50.000000

两个选项都产生:


大家一起:

import numpy as np
import pandas as pd
from matplotlib import pyplot as plt

np.random.seed(5)
n = 100
df = pd.DataFrame({'user': np.random.choice(list("ABCD"), size=n),
                   'answer': np.random.choice([1, 0, -1], size=n)})

plot_df = df[df['answer'].ne(-1)].groupby('user').aggregate(
    good_answer=('answer', 'sum'),
    total_answer=('answer', 'size')
)
plot_df['pct'] = (plot_df['good_answer'] / plot_df['total_answer'] * 100)

ax = plot_df.plot(
    y='pct', kind='bar', rot=0,
    title='Percentage of Good Answers',
    ylim=[0, 100],
    label='Percent Good'
)

# Add Labels on Top of Bars
for container in ax.containers:
    ax.bar_label(container, fmt='%.2f%%')

plt.show()

【讨论】:

    【解决方案2】:

    这是一个示例解决方案,假设您要根据过滤后的数据框计算百分比。

    import pandas as pd 
    import numpy as np 
    
    df_sample = pd.DataFrame(np.random.randint(-1,2,size=(10, 1)), columns=['answer'])
    df_sample['user'] = [i for i in 'a b c d e f a b c d'.split(' ')]
    df_filtered = df_sample[df_sample.answer>-1]
    
    
    print(df_filtered.groupby('user').agg({'answer' : lambda x: x.sum()/len(df_filtered)*100}))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-10-19
      • 1970-01-01
      • 1970-01-01
      • 2021-05-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多