Pandas 基于级别为 1 的 groupby 创建百分位数字段

Pandas create percentile field based on groupby with level 1

给定以下数据框:

import pandas as pd    
df = pd.DataFrame({
    ('Group', 'group'): ['a','a','a','b','b','b'],
    ('sum', 'sum'): [234, 234,544,7,332,766]
    })

我想创建一个新字段,用于计算 "group" 中每组 "sum" 每个值的百分位数。问题是,我有 2 header 列,无法弄清楚如何避免出现错误:

ValueError: level > 0 only valid with MultiIndex

当我运行这个:

df=df.groupby('Group',level=1).sum.rank(pct=True, ascending=False)

我需要将 header 保持在相同的结构中。

提前致谢!

要按第一列 ('Group', 'group') 分组并计算 ('sum', 'sum') 列的排名,请使用:

In [106]: df['rank'] = (df[('sum', 'sum')].groupby(df[('Group', 'group')]).rank(pct=True, ascending=False))

In [107]: df
Out[107]: 
  Group  sum      rank
  group  sum          
0     a  234  0.833333
1     a  234  0.833333
2     a  544  0.333333
3     b    7  1.000000
4     b  332  0.666667
5     b  766  0.333333

请注意,.rank(pct=True) 计算的是 百分比 排名,而不是 百分位数 。要计算百分位数,您可以使用 scipy.stats.percentileofscore.

import scipy.stats as stats
df['percentile'] = (df[('sum', 'sum')].groupby(df[('Group', 'group')])
    .apply(lambda ser: 100-pd.Series([stats.percentileofscore(ser, x, kind='rank') 
           for x in ser], index=ser.index)))

产量

  Group  sum      rank percentile
  group  sum                     
0     a  234  0.833333  50.000000
1     a  234  0.833333  50.000000
2     a  544  0.333333   0.000000
3     b    7  1.000000  66.666667
4     b  332  0.666667  33.333333
5     b  766  0.333333   0.000000