Groupby DataFrame按其等级/百分位数计算

时间:2016-07-08 06:08:47

标签: python pandas group-by

您是否可以帮助我为此问题找到更好的解决方案,如下所示: 对于每个日期(在列中),我有值。我对它们进行排名并分为三组。我的目标是按低,中,上组对值进行分组,并计算组均值。我把DataFrame和我自己的解决方案放在下面。 有谁能建议更好的解决方案? 我的真实数据有10000行和300列。 任何申请或lambda方式更直接地做?谢谢。

value=DataFrame({'1/1/2000':[1,4,5,6,5],
             '1/1/2001':[3,7,8,9,4],
             '1/1/2002':[7,8,9,4,5]}, index=list('ABCDE'))
rank=value.apply(lambda x: pd.qcut(x, 3, labels=['low','mid','top']))
df=pd.DataFrame()
df['Value']=value.stack()
df['Rank']=rank.stack()
df1=df.reset_index()
df1.groupby(['Date','Rank']).mean()

enter image description here

enter image description here enter image description here

1 个答案:

答案 0 :(得分:1)

您只能使用一个stack,然后pd.qcut只能使用一列Value而不是DataFrame

df = value.stack()
          .reset_index(name='Value')
          .rename(columns={'level_0':'Type','level_1':'Date'})

df['Rank'] = pd.qcut(df.Value, 3, labels=['low','mid','top'])
print (df)

   Type      Date  Value Rank
0     A  1/1/2000      1  low
1     A  1/1/2001      3  low
2     A  1/1/2002      7  mid
3     B  1/1/2000      4  low
4     B  1/1/2001      7  mid
5     B  1/1/2002      8  top
6     C  1/1/2000      5  mid
7     C  1/1/2001      8  top
8     C  1/1/2002      9  top
9     D  1/1/2000      6  mid
10    D  1/1/2001      9  top
11    D  1/1/2002      4  low
12    E  1/1/2000      5  mid
13    E  1/1/2001      4  low
14    E  1/1/2002      5  mid
print (df.groupby(['Date','Rank'])['Value'].mean())
Date      Rank
1/1/2000  low     2.500000
          mid     5.333333
1/1/2001  low     3.500000
          mid     7.000000
          top     8.500000
1/1/2002  low     4.000000
          mid     6.000000
          top     8.500000
Name: Value, dtype: float64

print (df.groupby(['Date','Rank'])['Value'].mean().reset_index(name='Value'))
       Date Rank     Value
0  1/1/2000  low  2.500000
1  1/1/2000  mid  5.333333
2  1/1/2001  low  3.500000
3  1/1/2001  mid  7.000000
4  1/1/2001  top  8.500000
5  1/1/2002  low  4.000000
6  1/1/2002  mid  6.000000
7  1/1/2002  top  8.500000

编辑:

您也可以省略创建新列Rank并将其传递给groupby

df = value.stack()
          .reset_index(name='Rank')
          .rename(columns={'level_0':'Type','level_1':'Date'})

print (df)
   Type      Date  Rank
0     A  1/1/2000     1
1     A  1/1/2001     3
2     A  1/1/2002     7
3     B  1/1/2000     4
4     B  1/1/2001     7
5     B  1/1/2002     8
6     C  1/1/2000     5
7     C  1/1/2001     8
8     C  1/1/2002     9
9     D  1/1/2000     6
10    D  1/1/2001     9
11    D  1/1/2002     4
12    E  1/1/2000     5
13    E  1/1/2001     4
14    E  1/1/2002     5

print (df['Rank'].groupby([df.Date, 
                           pd.qcut(df.Rank, 3, labels=['low','mid','top'])])
                 .mean().reset_index(name='Value'))

       Date Rank     Value
0  1/1/2000  low  2.500000
1  1/1/2000  mid  5.333333
2  1/1/2001  low  3.500000
3  1/1/2001  mid  7.000000
4  1/1/2001  top  8.500000
5  1/1/2002  low  4.000000
6  1/1/2002  mid  6.000000
7  1/1/2002  top  8.500000