如何在Pandas中更新指定子集DataFrame的VALUE字段值?
Pandas实现指定PERSNR子集的VALUE汇总与更新
问题场景
我有一个包含约8000个PERSNR的DataFrame,结构示例如下(实际包含更多列):
| PERSNR | XYZ | DATE | VALUE |
|---|---|---|---|
| 22222 | a | Jan | 0,8 |
| 22222 | b | Jan | 0,2 |
| 22222 | a | Feb | 0,8 |
| 22222 | b | Feb | 0,2 |
需求如下:
- 针对已知PERSNR列表的子集,按
PERSNR和DATE汇总VALUE(忽略XYZ字段) - 将汇总结果赋值给对应
XYZ为"a"的行 - 将
XYZ为"b"的行的VALUE设为0 - 保留原DataFrame的其他所有数据
目标结果示例:
| PERSNR | XYZ | DATE | VALUE |
|---|---|---|---|
| 22222 | a | Jan | 1,0 |
| 22222 | b | Jan | 0,0 |
| 22222 | a | Feb | 1,0 |
| 22222 | b | Feb | 0,0 |
实现步骤
1. 预处理VALUE字段
示例中VALUE是逗号分隔的字符串(如0,8),需先转换为数值类型才能求和:
# 替换逗号为小数点,转成float类型 df['VALUE'] = df['VALUE'].str.replace(',', '.').astype(float)
2. 定义目标PERSNR子集
替换为你实际需要处理的PERSNR列表:
target_persnr = [22222, 11111] # 示例子集
3. 生成汇总数据
针对目标子集,按PERSNR和DATE分组求和:
# 筛选目标子集,分组计算VALUE总和 sum_df = df[df['PERSNR'].isin(target_persnr)].groupby(['PERSNR', 'DATE'])['VALUE'].sum().reset_index() # 重命名列,避免和原表VALUE冲突 sum_df = sum_df.rename(columns={'VALUE': 'SUM_VALUE'})
4. 合并并更新原DataFrame
将汇总数据合并回原表,按规则更新VALUE:
import numpy as np # 左连接汇总表到原表,保留所有原始行 df = df.merge(sum_df, on=['PERSNR', 'DATE'], how='left') # 按规则更新VALUE: # - 目标子集内且XYZ='a'的行:用汇总值替换 # - 目标子集内且XYZ='b'的行:设为0 # - 其他行:保留原VALUE df['VALUE'] = np.where( df['PERSNR'].isin(target_persnr) & (df['XYZ'] == 'a'), df['SUM_VALUE'], np.where( df['PERSNR'].isin(target_persnr) & (df['XYZ'] == 'b'), 0.0, df['VALUE'] ) ) # 删除临时的汇总列 df = df.drop(columns=['SUM_VALUE'])
5. 可选:恢复VALUE的逗号分隔格式
如果需要回到原始的字符串格式:
df['VALUE'] = df['VALUE'].astype(str).str.replace('.', ',')
完整代码示例
import pandas as pd import numpy as np # 构造示例DataFrame data = { 'PERSNR': [22222, 22222, 22222, 22222, 33333, 33333], 'XYZ': ['a', 'b', 'a', 'b', 'a', 'b'], 'DATE': ['Jan', 'Jan', 'Feb', 'Feb', 'Jan', 'Jan'], 'VALUE': ['0,8', '0,2', '0,8', '0,2', '0,5', '0,5'] } df = pd.DataFrame(data) # 目标PERSNR子集 target_persnr = [22222] # 预处理VALUE df['VALUE'] = df['VALUE'].str.replace(',', '.').astype(float) # 生成汇总表 sum_df = df[df['PERSNR'].isin(target_persnr)].groupby(['PERSNR', 'DATE'])['VALUE'].sum().reset_index() sum_df = sum_df.rename(columns={'VALUE': 'SUM_VALUE'}) # 合并并更新数据 df = df.merge(sum_df, on=['PERSNR', 'DATE'], how='left') df['VALUE'] = np.where( df['PERSNR'].isin(target_persnr) & (df['XYZ'] == 'a'), df['SUM_VALUE'], np.where( df['PERSNR'].isin(target_persnr) & (df['XYZ'] == 'b'), 0.0, df['VALUE'] ) ) df = df.drop(columns=['SUM_VALUE']) # 转回逗号分隔格式(可选) df['VALUE'] = df['VALUE'].astype(str).str.replace('.', ',') print(df)
执行后输出:
PERSNR XYZ DATE VALUE 0 22222 a Jan 1,0 1 22222 b Jan 0,0 2 22222 a Feb 1,0 3 22222 b Feb 0,0 4 33333 a Jan 0,5 5 33333 b Jan 0,5
内容的提问来源于stack exchange,提问作者Mike
相关产品推荐
相关产品推荐

