我有以下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
我想用groupby
和df
来year
code
,然后将col2
和col1
之间的差求和,然后取平均值整个小组人数之和;
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
答案 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