重采样和分组,均值和求和

resample and groupby, mean and sum

这是我的输入数据框

d1 = pd.Timestamp(2020,8,1)
d2 = pd.Timestamp(2020,9,1)
somedict = {'a':[2,3,2,3,4], 'b':['one','two','two','two','one'], 'c':['yes','no','yes','yes','no'] ,'d':[d1,d1,d2,d1,d2], 'e':[8,7,7,6,9]}
df = pd.DataFrame(somedict)
df.set_index('d',inplace=True)

我想使用 df.groupby('b') 按列 b 对其进行分组,并使用 df.resample('M') 按月重新采样。分组和重采样后,我想看到两件事

  1. 我们在 c
  2. 列中有多少个 yes 实例
  3. a 列的总和除以 e
  4. 列的总和

因此,结果输出应按 b 列中的类别 one, two 分组,并且 sums/number 个实例应每月显示

我试过 运行 (df['c'] == 'yes').resample('M').mean() 这几乎回答了问题 1,但是由于 b 不再是结果的一部分,我不能写 groupby('b').

试试 pd.Grouper:

groups = df.groupby(['b',pd.Grouper(freq='M')])

out = pd.DataFrame({'count_c': groups['c'].apply(lambda x: x.eq('yes').sum()),
                    'a/e': groups['a'].sum()/groups['e'].sum()
                   })

输出:

                count_c       a/e
b   d                            
one 2020-08-31        1  0.250000
    2020-09-30        0  0.444444
two 2020-08-31        1  0.461538
    2020-09-30        1  0.285714

或者,您可以绕过 apply 函数并使用管道代替(速度略有提高):

(df.assign(c=lambda df: df['c'].map({"yes":1,"no":0}))
   .groupby(['b', pd.Grouper(freq='M')])
   .pipe(lambda df: pd.DataFrame({"count_c": df['c'].sum(), 
                                  "a/e": df['a'].sum()/df['e'].sum()}))
 )
 
                count_c       a/e
b   d                            
one 2020-08-31        1  0.250000
    2020-09-30        0  0.444444
two 2020-08-31        1  0.461538
    2020-09-30        1  0.285714