我有一个如下数据框:
+-----------------------+
| id | weight | value |
+-----------------------+
| i1 | 1 | 0 |
| i1 | 2 | 3 |
| i1 | 3 | 6 |
| i2 | 1 | 2 |
| i2 | 2 | 2 |
| i3 | 2 | 2 |
+-----------------------+
,我想做几个汇总,以根据id
计算以下内容:
预期输出如下:
+------------------------------------------+
| new_id | avg_val | val_sum | val_count |
+------------------------------------------+
| i1 | 4 | 9 | 2 |
| i2 | 2 | 4 | 2 |
| i3 | 2 | 2 | 1 |
+------------------------------------------+
请注意,id
列名称是输入,可能与旧输入不同或相似。
我知道我可以通过多种方法实现这一目标,但是知道我们正在处理的数据量非常大时,推荐的最快的方法是什么?
我想到的可能的解决方案:
为每个聚合分组并合并
in_df = pd.DataFrame({
'id': ['i1', 'i1', 'i1', 'i2', 'i2', 'i3'],
'weight': [1, 2, 3, 1, 2, 2],
'value': [0, 3, 6, 2, 2, 2]
})
out_df = pd.DataFrame()
out_df['new_id'] = in_df['id'].unique()
grouped_df = in_df.groupby('id').apply(lambda group: (group['weight'] * group['value']).sum() / max(group['weight'].sum(), 0.001)).reset_index(name='avg_val')
out_df = pd.merge(out_df,
grouped_df,
left_on='new_id',
right_on='id',
how='left')
out_df.drop('id') # Dangerous if the `new_id` name is similar to `id`
# Go on like this for every aggregation ...
print(out_df)
分组并为每个聚合更新
in_df = pd.DataFrame({
'id': ['i1', 'i1', 'i1', 'i2', 'i2', 'i3'],
'weight': [1, 2, 3, 1, 2, 2],
'value': [0, 3, 6, 2, 2, 2]
})
out_df = pd.DataFrame(columns=['new_id', 'avg_val', 'val_sum', 'val_count'])
out_df['new_id'] = in_df['id'].unique()
out_df = out_df.set_index('new_id')
grouped_df = in_df.groupby('id').apply(lambda group: (group['weight'] * group['value']).sum() / max(group['weight'].sum(), 0.001)).reset_index(name='avg_val')
grouped_df = grouped_df.set_index('id')
out_df.update(grouped_df)
# Go on like this for every aggregation ...
print(out_df)
答案 0 :(得分:2)
您需要:
res = df.assign(wv = df['weight'].mul(df['value'])).groupby('id').agg({
'wv': 'sum',
'weight': 'sum',
'value':['sum', np.count_nonzero]
})
res['avg_val'] = res['wv'] / res['weight']
res = res.drop(['wv', 'weight'],1)
res.columns = ['val_sum', 'val_count', 'avg_val']
输出:
val_sum val_count avg_val
id
i1 9 2 4.0
i2 4 2 2.0
i3 2 1 2.0
您的两个问题都使用apply
+ lambda
,这样您就可以遍历每个组(在许多其他事物中),而此代码则无此作用。这就是为什么它更快,更有效。