Pandas对分组数据执行操作

时间:2016-11-03 18:55:53

标签: python pandas dataframe

我想在pandas数据帧中对分组数据执行一项功能。 我有下面的df并且迭代地执行以下操作,但是认为这应该由pandas groupby完成。

import pandas as pd
import scipy
from scipy.stats import mstats 

df = pd.DataFrame({'cfs': [147248, 94894, 81792, 176011, 208514, 18111, 56742, 154900, 32778, 142333, 45267, 145211, 3429, 1258, 65439], 'Alternatives':['A','B','C']*5})

alternatives = list(set(df['Alternatives']))

df2 = pd.DataFrame()

for alternative in alternatives:
    alt = pd.DataFrame(df[(df.Alternatives == alternative)])
    alt = alt.sort_values(['cfs'])
    alt['rank'] = alt['cfs'].rank()
    alt['pp'] = 1 - scipy.stats.mstats.plotting_positions(alt['cfs'],0,0) 
    df2 = df2.append(alt) 

输出:

Alternatives     cfs  rank        pp
12            A    3429   1.0  0.833333
6             A   56742   2.0  0.666667
9             A  142333   3.0  0.500000
0             A  147248   4.0  0.333333
3             A  176011   5.0  0.166667
5             C   18111   1.0  0.833333
8             C   32778   2.0  0.666667
14            C   65439   3.0  0.500000
2             C   81792   4.0  0.333333
11            C  145211   5.0  0.166667
13            B    1258   1.0  0.833333
10            B   45267   2.0  0.666667
1             B   94894   3.0  0.500000
7             B  154900   4.0  0.333333
4             B  208514   5.0  0.166667

我可以通过

获得排名
df['rank'] = df['cfs'].groupby(df['Alternatives']).rank()

但我无法获得策划位置。我最接近的是:

group = df['cfs'].groupby(df['Alternatives']).apply(scipy.stats.mstats.plotting_positions,0,0 ) 

这给了我一个带有正确数据的熊猫系列,但我想做的是:

df['pp'] = df['cfs'].groupby(df['Alternatives']).apply(scipy.stats.mstats.plotting_positions,0,0)  

但是,这只会返回一列NaN

由于

1 个答案:

答案 0 :(得分:2)

def func(x):
    x['pp'] = 1 - scipy.stats.mstats.plotting_positions(x.cfs, 0, 0)
    return x

df.groupby('Alternatives').apply(func)

   Alternatives     cfs        pp
0             A  147248  0.333333
1             B   94894  0.500000
2             C   81792  0.333333
3             A  176011  0.166667
4             B  208514  0.166667
5             C   18111  0.833333
6             A   56742  0.666667
7             B  154900  0.333333
8             C   32778  0.666667
9             A  142333  0.500000
10            B   45267  0.666667
11            C  145211  0.166667
12            A    3429  0.833333
13            B    1258  0.833333
14            C   65439  0.500000

调试groupby有助于使用get_group

g = df.groupby('Alternatives').get_group('A')
g.apply(whatever)  # test on a single group and then apply to all at once