如何在分组后的Pandas DataFrame中为每个子组添加基于指定行值的新列?
解决Pandas分组后添加子组特定值列的问题
没问题,我来帮你搞定这个需求!先确认下你的场景:每个ID+Month的子组里,都有一行B=False的记录,你要把这行的Salary值填充到该子组所有行的NEW_Salary列里对吧?下面给你两种简单易懂的实现方法:
方法一:筛选+合并(直观易理解)
如果你觉得分组函数有点绕,这个方法逻辑最清晰——先提取每个组需要填充的值,再通过关联字段把值“复制”到组内所有行:
import pandas as pd # 先构造你的DataFrame data_ = {'ID': [777, 777, 777,777,777,777], 'Month':[1,1,1,2,2,2], 'Salary': [130,170,50,140,180,60], 'O': ["AC","BR","BR","AC","BR","BR"], 'D':["LF","AC","LF","LF","AC","LF"], 'B':[True,True,False,True,True,False]} data = pd.DataFrame(data=data_) # 第一步:筛选出所有B=False的行,保留ID、Month和Salary列,并重命名Salary为NEW_Salary target_salaries = data[data['B'] == False][['ID', 'Month', 'Salary']].rename(columns={'Salary': 'NEW_Salary'}) # 第二步:用ID和Month作为键,把目标值合并到原DataFrame data = pd.merge(data, target_salaries, on=['ID', 'Month'], how='left')
方法二:groupby.transform(Pandas原生分组方案)
transform是Pandas专门为这种分组后广播值的场景设计的工具,它会对每个分组执行函数,自动把结果扩展到组内的每一行:
import pandas as pd # 构造DataFrame(同上) data_ = {'ID': [777, 777, 777,777,777,777], 'Month':[1,1,1,2,2,2], 'Salary': [130,170,50,140,180,60], 'O': ["AC","BR","BR","AC","BR","BR"], 'D':["LF","AC","LF","LF","AC","LF"], 'B':[True,True,False,True,True,False]} data = pd.DataFrame(data=data_) # 定义函数:提取当前组中B=False对应的Salary值 def get_false_salary(group): # 假设每个组只有一个B=False的行,用iloc[0]取第一个值 return group[group['B'] == False]['Salary'].iloc[0] # 分组后用transform添加新列 data['NEW_Salary'] = data.groupby(["ID","Month"]).transform(get_false_salary)['Salary']
结果验证
不管用哪种方法,最终你的DataFrame的NEW_Salary列都会呈现预期结果:
| ID | Month | Salary | O | D | B | NEW_Salary | |
|---|---|---|---|---|---|---|---|
| 0 | 777 | 1 | 130 | AC | LF | True | 50 |
| 1 | 777 | 1 | 170 | BR | AC | True | 50 |
| 2 | 777 | 1 | 50 | BR | LF | False | 50 |
| 3 | 777 | 2 | 140 | AC | LF | True | 60 |
| 4 | 777 | 2 | 180 | BR | AC | True | 60 |
| 5 | 777 | 2 | 60 | BR | LF | False | 60 |
鲁棒性优化(可选)
如果你的数据里可能存在某个ID+Month组没有B=False的行,可以加个默认值处理避免报错:
- 方法一可以在合并后填充默认值:
data = pd.merge(data, target_salaries, on=['ID', 'Month'], how='left').fillna({'NEW_Salary': 0})
- 方法二可以在分组函数里加判断:
def get_false_salary(group): false_rows = group[group['B'] == False] return false_rows['Salary'].iloc[0] if not false_rows.empty else 0 # 也可以用NaN作为默认值
内容的提问来源于stack exchange,提问作者the phoenix
相关产品推荐
相关产品推荐

