如何对分组后的Pandas DataFrame按规则生成NEW_Salary列?
问题描述
现有Pandas DataFrame,需按Year、Month、Day列分组,在每个组内创建NEW_Salary列,规则如下:
- 将
Combination为True的行(如Name为KimJason、KimTom的行)的Salary值,分别加到对应Name组成部分的Combination为False的行(如KimJason对应Kim和Jason行,KimTom对应Kim和Tom行)的Salary上; Combination为True的行的NEW_Salary值与原Salary值保持一致。
修正后的示例数据代码:
import pandas as pd data = { "Year": [2002,2002,2002,2002,2002,2010,2010,2010,2010,2010], "Name": ['Jason','Tom','KimJason','KimTom','Kim','Jason','Tom','KimJason','KimTom','Kim'], "Combination": [False,False,True,True,False,False,False,True,True,False], "Salary": [10,20,25,25,30,20,30,35,35,40] } df = pd.DataFrame(data) # 修正拼写错误:pd.dataframe → pd.DataFrame
通用实现方案
以下方法完全不受分组数量限制,核心通过groupby().apply()对每个分组独立处理,适配任意分组规模:
def process_group(group): # 初始化NEW_Salary为原Salary,直接满足组合行的薪资保留规则 group['NEW_Salary'] = group['Salary'].copy() # 提取所有组合行,拆分Name并构建薪资累加映射 combo_rows = group[group['Combination']] salary_add_map = {} for _, row in combo_rows.iterrows(): # 拆分驼峰式命名的组合名(如KimJason拆为Kim、Jason),可根据实际命名规则调整 # 若为下划线分隔,可改为 row['Name'].split('_') split_names = [row['Name'][:3], row['Name'][3:]] for name in split_names: salary_add_map[name] = salary_add_map.get(name, 0) + row['Salary'] # 给非组合行累加对应薪资,无匹配项则加0(保持原薪资) non_combo_mask = group['Combination'] == False group.loc[non_combo_mask, 'NEW_Salary'] += group.loc[non_combo_mask, 'Name'].map(salary_add_map).fillna(0) return group # 按目标列分组处理,实际使用时替换为['Year', 'Month', 'Day'] result_df = df.groupby(['Year']).apply(process_group).reset_index(drop=True) print(result_df)
关键细节说明
- 命名拆分适配:示例中按固定长度拆分组合名,若你的数据是驼峰命名(如KimJason),可改用正则拆分:
import re; split_names = re.findall('[A-Z][a-z]*', row['Name']),适配更通用的组合名格式; - 分组通用性:
groupby().apply()会自动遍历所有分组,不管分组数量多少,每个分组都会独立执行逻辑,完全适配大规模分组场景; - 异常处理:
fillna(0)确保没有对应组合行的非组合行不会出现NaN,保持原薪资数值不变。
示例输出(部分)
| Year | Name | Combination | Salary | NEW_Salary |
|---|---|---|---|---|
| 2002 | Jason | False | 10 | 35 |
| 2002 | Tom | False | 20 | 45 |
| 2002 | KimJason | True | 25 | 25 |
| 2002 | KimTom | True | 25 | 25 |
| 2002 | Kim | False | 30 | 80 |
| 2010 | Jason | False | 20 | 55 |
内容的提问来源于stack exchange,提问作者the phoenix
相关产品推荐
相关产品推荐

