如何在Pandas GroupBy操作中修改指定分组的DataFrame?
问题描述
现有包含多分组的DataFrame:
import pandas as pd df = pd.DataFrame({ 'time': ['01/01/2023', '02/01/2023', '01/01/2023', '02/01/2023'], 'name': ['DE_STC', 'DE_STC','FR_STC', 'FR_STC'], 'value': [1, 2, 3, 4]})
希望基于name字段分组,将另一个DataFrame的数值多次累加到指定分组。待累加的DataFrame示例:
# 待累加的DataFrame df_fr_stc = pd.DataFrame({ 'time': ['01/01/2023', '02/01/2023'], 'value': [-1, -1]})
当前尝试的代码:
df_grouped = df.groupby('name') for i in range(3): df_temp = df_grouped.get_group('DE_STC') df_temp = pd.concat([df_temp, df_fr_stc], sort=False).groupby(['time']).sum().reset_index()
现在需要类似set_group()的方法,用新生成的DataFrame替换指定分组,比如:
df_grouped.set_group(pd.concat([df_grouped.get_group('FR_STC'), df_fr_stc], sort=False).groupby(['time']).sum().reset_index())
期望最终结果:
> df time name value 0 01/01/2023 DE_STC 1 1 02/01/2023 DE_STC 2 2 01/01/2023 FR_STC 0 3 02/01/2023 FR_STC 1
补充说明(实际业务场景)
实际业务中的DataFrame结构:
> df time name value 0 01/01/2023 00:00:00 DE_STC 1 1 01/01/2023 01:00:00 DE_STC 1 ... 8759 31/12/2023 23:00:00 DE_STC 1 8760 01/01/2023 00:00:00 FR_STC 2 8761 01/01/2023 01:00:00 FR_STC 2 ... 17519 31/12/2023 23:00:00 FR_STC 2 ...
需要处理订单式数值累加:比如给所有DE_STC数据加3,或给2023年每小时的FR_STC数据加7。待累加的DataFrame示例:
> df_fr_stc time name value 0 01/01/2023 00:00:00 FR_STC 7 1 01/01/2023 01:00:00 FR_STC 7 ... 8759 31/12/2023 23:00:00 FR_STC 7 > df_de_stc time name value 0 01/01/2023 00:00:00 DE_STC 3 1 01/01/2023 01:00:00 DE_STC 3 ... 8759 31/12/2023 23:00:00 DE_STC 3
生成2023年按小时分布的DataFrame代码(存在问题的部分标注):
from datetime import timedelta for i in df_orders: dt_start = i[29] dt_end = i[28] - timedelta(hours=1) dti = pd.date_range(dt_start, dt_end, freq='H').to_pydatetime() # 指定小时频率 df = pd.DataFrame(dti, columns=['time']) df['value'] = i[12] # 添加常量值列 # 此处操作存在问题,无法直接修改分组后的DataFrame df_op_test.get_group(order_group) = pd.concat([df_op_test.get_group(order_group), df], sort=False).groupby(['time']).sum().reset_index()
期望最终结果:
> df time name value 0 01/01/2023 00:00:00 DE_STC 4 1 01/01/2023 01:00:00 DE_STC 4 ... 8759 31/12/2023 23:00:00 DE_STC 4 8760 01/01/2023 00:00:00 FR_STC 9 8761 01/01/2023 01:00:00 FR_STC 9 ... 17519 31/12/2023 23:00:00 FR_STC 9 ...
解决方案
Pandas的GroupBy对象本身不支持直接修改分组(没有set_group方法),但可以通过以下两种方式实现需求:
方法1:拆分分组后替换再合并
- 将分组后的每个组转换为字典,键是分组名,值是对应DataFrame
- 修改指定分组的DataFrame
- 重新合并所有分组得到新的DataFrame
示例代码:
# 初始分组 df_grouped = df.groupby('name') # 转换为字典 group_dict = dict(list(df_grouped)) # 修改FR_STC分组:合并原分组与待累加数据,按time求和 updated_fr = pd.concat([group_dict['FR_STC'], df_fr_stc], sort=False).groupby('time').sum().reset_index() updated_fr['name'] = 'FR_STC' # 恢复name列 # 替换字典中的FR_STC分组 group_dict['FR_STC'] = updated_fr # 合并所有分组得到最终DataFrame df_final = pd.concat(group_dict.values(), ignore_index=True)
方法2:直接合并后全局分组求和(更高效)
不需要单独操作分组,直接将原DataFrame与所有待累加DataFrame合并,然后按name和time分组求和,这种方法更适合批量累加操作。
示例代码:
# 假设需要多次累加,比如给FR_STC加3次df_fr_stc # 先复制待累加数据3次 df_fr_stc_repeated = pd.concat([df_fr_stc]*3, ignore_index=True) df_fr_stc_repeated['name'] = 'FR_STC' # 补充name列 # 合并原数据与累加数据 combined_df = pd.concat([df, df_fr_stc_repeated], ignore_index=True) # 按name和time分组求和 df_final = combined_df.groupby(['name', 'time'], as_index=False).sum()
针对实际业务场景,推荐方法2,因为当有多个累加操作时,只需将所有待累加的DataFrame(补充好name列)与原DataFrame合并,再一次分组求和即可,代码更简洁高效,避免循环操作分组。
内容的提问来源于stack exchange,提问作者R13mus
相关产品推荐
相关产品推荐

