pandas groupby将两列之间的差异求和,并获得每组的平均值

时间:2019-06-19 11:21:32

标签: python python-3.x pandas dataframe group-by

我有以下df

year    code    col1   col2
2019    1       2      3
2019    1       3      5
2019    1       2      4
2018    2       1      4
2018    2       2      6

我想用groupbydfyear code,然后将col2col1之间的差求和,然后取平均值整个小组人数之和;

df.apply(lambda row: (row['col_2'] - row['col_1']).mean(level=[0, 1]).reset_index(name='avg_num')

这段代码似乎是在计算差异的平均值,而不是将差异相加并除以组大小,那么该如何解决呢?

year    code    col1   col2    avg_num
2019    1       2      3       1.66
2019    1       3      5       1.66
2019    1       2      4       1.66
2018    2       1      4       3.5
2018    2       2      6       3.5

3 个答案:

答案 0 :(得分:2)

GroupBy.transform用于由汇总值填充的新列:

df['avg_num'] = (df.assign(avg_num=df.col2 - df.col1)
                   .groupby(['year', 'code'])['avg_num']
                   .transform('mean').round(2))
print (df)
   year  code  col1  col2  avg_num
0  2019     1     2     3     1.67
1  2019     1     3     5     1.67
2  2019     1     2     4     1.67
3  2018     2     1     4     3.50
4  2018     2     2     6     3.50

另一个没有assign的解决方案,但是必须将列传递给groupby,例如df['year']df['code']

df['avg_num'] = ((df['col2'] - df['col1']).groupby([df['year'], df['code']])
                                          .transform('mean').round(2))
print (df)
   year  code  col1  col2  avg_num
0  2019     1     2     3     1.67
1  2019     1     3     5     1.67
2  2019     1     2     4     1.67
3  2018     2     1     4     3.50
4  2018     2     2     6     3.50

答案 1 :(得分:1)

我们可以创建一个中间表来保存聚合值,然后将其重新连接到原始DataFrame。

aggs = df.assign(avg_num=df.col2 - df.col1) \
         .groupby(['year', 'code'], as_index=False)['avg_num'].mean().round(2)

print(aggs)

   year  code  avg_num
0  2018     2   3.50
1  2019     1   1.67

df.merge(aggs, how='inner', left_on=['year', 'code'], right_on=['year', 'code'])

   year  code  col1  col2  avg_num
0  2019     1     2     3   1.67
1  2019     1     3     5   1.67
2  2019     1     2     4   1.67
3  2018     2     1     4   3.50
4  2018     2     2     6   3.50

答案 2 :(得分:1)

data = df.groupby(['year','code']).apply(lambda x: sum(list(abs(x.col2 - x.col1))) / len(list(abs(x.col2 - x.col1)))).reset_index().rename({0:'avg_num'},axis=1)

df.merge(data, on='year').drop('code_y', axis=1).rename({'code_x':'code'}, axis=1)

输出

   year  code  col1  col2   avg_num
0  2019     1     2     3  1.666667
1  2019     1     3     5  1.666667
2  2019     1     2     4  1.666667
3  2018     2     1     4  3.500000
4  2018     2     2     6  3.500000