在 Pandas 中聚合到没有循环的当前行

Aggregate up to current row without loops in Pandas

我有一个包含 ideventmetric 列的数据集:

df = pd.DataFrame([['a','x', 1], 
                  ['a','x',2],  
                  ['b','y',3],  
                  ['a','z',4],  
                  ['a','j',5]], columns = ['id','event','metric'])

   id event metric
0   a   x   1
1   a   x   2
2   b   y   3
3   a   z   4
4   a   j   5

我需要按 idevent 对其进行分组以获得 summeanstdmin、[= metric 的 22=] 聚合不仅包括给定 "id-event" 组的值,而且还包括 所有先前事件的 metric给出 id。换句话说,我需要对给定行之前的所有行进行聚合。

期望的输出:

   id event sum mean        std       min   max
0   a   j   12  3.000000    1.825742    1   5
1   a   x   3   1.500000    0.707107    1   2
2   a   z   7   2.333333    1.527525    1   4
3   b   y   3   3.000000    NaN         3   3

当我为每个组过滤我的数据框时,我尝试了 for-loop 方法。但问题是我有大约 2000 万行,所以计算时间很长。我正在尝试解决这个 没有循环 .

您需要使用 groupby

df.groupby(["id", "event"])["metric"].describe()

您需要 id 上的 sort_values 选项 quicksort 才能对 id 进行排序,但在其他列上保持原始顺序。接下来,id 上的 groupbysum, mean, std, min, max 上的 expanding。最后,pd.concatevent 列添加到最终 df。 drop_duplicates 仅保留每组的最后一行 id-eventsort_values 以获得您想要的顺序。

df1 = df.sort_values('id', kind='quicksort')
df2 = df1.groupby('id').expanding().metric.agg(['sum', 'mean', 'std', 'min', 'max']).droplevel(1)
df_final = (pd.concat([df1.set_index('id').event, df2], axis=1).reset_index().
              drop_duplicates(subset=['id', 'event'], keep='last').
              sort_values(['id', 'event']))

Out[96]:
  id event   sum      mean       std  min  max
3  a     j  12.0  3.000000  1.825742  1.0  5.0
1  a     x   3.0  1.500000  0.707107  1.0  2.0
2  a     z   7.0  2.333333  1.527525  1.0  4.0
4  b     y   3.0  3.000000       NaN  3.0  3.0