如何对 pandas 列进行分组以创建新的百分比列

How do I group a pandas column to create a new percentage column

我有一个 pandas 数据框,如下所示:

mydict ={
        'person': ['Jenny', 'Jenny', 'David', 'David', 'Max', 'Max'],
        'fruit': ['Apple', 'Orange', 'Apple', 'Orange', 'Apple', 'Orange'],
        'eaten': [25, 75, 15, 5, 10, 10]
    }

df = pd.DataFrame(mydict) 

    person fruit   eaten
    Jenny  Apple   25
    Jenny  Orange  75
    David  Apple   15
    David  Orange  5
    Max    Apple   10
    Max    Orange  10 

我想转换成:

person  apple_percentage  orange_percentage
Jenny   0.25              0.75
David   0.75              0.25
Max     0.50              0.50

我猜我必须以某种身份使用 groupby 才能做到这一点,但无法找到一种干净的 Pythonic 方式来做到这一点?

使用 DataFrame.pivot 除以 sums:

df = df.pivot('person','fruit','eaten').add_suffix('_percentage')
df = df.div(df.sum(axis=1), axis=0)
print (df)
fruit   Apple_percentage  Orange_percentage
person                                     
David               0.75               0.25
Jenny               0.25               0.75
Max                 0.50               0.50

可以堆叠和取消堆叠() 和聚合

    df=df.set_index(['person','fruit']).stack().unstack('fruit').add_suffix('_percentage')#)

df = df.div(df.sum(axis=1), axis=0).reset_index().drop(columns='level_1')



 fruit person  Apple_percentage  Orange_percentage
0      David              0.75               0.25
1      Jenny              0.25               0.75
2        Max              0.50               0.50

另一个选项是 pandas' 交叉表:

(pd.crosstab(index = df.person, 
            columns = df.fruit, 
            values = df.eaten, 
            aggfunc = 'mean', 
            normalize='index')
   .add_suffix('_percentage')
   .rename_axis(columns=None)
)
 
        Apple_percentage  Orange_percentage
person
David               0.75               0.25
Jenny               0.25               0.75
Max                 0.50               0.50

您也可以使用 pipe 方法,尽管在这种情况下,它不会使代码更清晰(这违背了 pipe 函数的目的):

(df.assign(eaten = df.groupby('person')
                     .pipe(lambda grp: df.eaten / 
                                       grp.eaten.transform('sum'))
           )
  .pivot('person', 'fruit', 'eaten')
  .add_suffix('_percentage')
  .rename_axis(columns=None)
)
        Apple_percentage  Orange_percentage
person
David               0.75               0.25
Jenny               0.25               0.75
Max                 0.50               0.50