Pandas避免合并操作:按#PROD和#CURRENCY分组填充TP字段
问题与解决方案
问题描述
现有如下结构的DataFrame:
import pandas as pd data=[['Offshore','NY','A','USD','ABC_USD'],['Onshore','BH','A','USD',''], ['Onshore','AE','A','USD',''],['Offshore','NY','A','GBP','GBP_ABC'],['Onshore','BH','A','GBP',''], ['Onshore','AE','A','GBP',''],['Onshore','BH','A','EUR',''],['Onshore','AE','A','EUR','']] df = pd.DataFrame(data, columns=['Loc', 'Country','#PROD','#CURRENCY','TP'])
需求:按#PROD和#CURRENCY字段分组,将Loc列为Onshore的行的TP字段替换为同组内Offshore行的TP值,要求无需创建两个DataFrame再进行连接。目前已通过拆分再连接的方式实现,希望得到更简洁的实现方法。
简洁实现方式
以下几种方法均可在原DataFrame上直接完成操作,无需拆分连接:
方法1:用groupby.transform提取分组内Offshore的TP值
适用于每组最多只有一条Offshore行的场景:
df['TP'] = df.groupby(['#PROD', '#CURRENCY']).apply( lambda g: g['TP'].mask(g['Loc'] == 'Onshore', g[g['Loc'] == 'Offshore']['TP'].iloc[0] if not g[g['Loc'] == 'Offshore'].empty else g['TP']) ).reset_index(drop=True)
方法2:结合mask与groupby.transform简化填充
先将Onshore行的TP标记为空,再用分组内的第一个非空TP值填充(需确保Offshore行的TP是组内唯一非空值):
# 将Onshore行的TP转为NaN,再用分组内的第一个有效值填充 df['TP'] = df['TP'].mask(df['Loc'] == 'Onshore').groupby([df['#PROD'], df['#CURRENCY']]).transform('first')
方法3:鲁棒性兼容(处理无Offshore行的分组)
如果存在分组没有Offshore行(如示例中的EUR组),可保留原空值,逻辑更通用:
def fill_onshore_tp(group): offshore_records = group[group['Loc'] == 'Offshore'] if not offshore_records.empty: # 取Offshore行的TP值,覆盖同组所有行的TP group['TP'] = offshore_records['TP'].iloc[0] return group # 应用分组逻辑,不保留分组键索引 df = df.groupby(['#PROD', '#CURRENCY'], group_keys=False).apply(fill_onshore_tp)
执行效果
所有Onshore行的TP会被替换为同组Offshore行的TP值;无Offshore行的分组则保持原空值,完全符合需求。
内容的提问来源于stack exchange,提问作者Number Logic
相关产品推荐
相关产品推荐

