基于其他列与行的值设置DataFrame的Value列值
问题描述
我有一个包含Date、Location、Category、Value四列的DataFrame df。需要按Date和Location分组,将每组中Category为5及以上的行的Value值,替换为该组内Category=5的行的Value值。
原数据示例
df: Date Location Category Value 20220101 FE 1 0.23 20220101 FE 2 0.24 20220101 FE 3 0.26 20220101 FE 4 0.27 20220101 FE 5 0.28 20220101 FE 6 0.30 20220101 RP 5 0.32 20220101 RP 6 0.35 20220102 FE 1 0.20 20220102 FE 2 0.23 20220102 FE 3 0.25 20220102 FE 4 0.26 20220102 FE 5 0.28 20220102 FE 6 0.32
期望处理后的数据
df_new: Date Location Category Value 20220101 FE 1 0.23 20220101 FE 2 0.24 20220101 FE 3 0.26 20220101 FE 4 0.27 20220101 FE 5 0.28 20220101 FE 6 0.28 <-- 替换为Category==5行的Value值 20220101 RP 5 0.32 20220101 RP 6 0.32 <-- 替换为Category==5行的Value值 20220102 FE 1 0.20 20220102 FE 2 0.23 20220102 FE 3 0.25 20220102 FE 4 0.26 20220102 FE 5 0.28 20220102 FE 6 0.28 <-- 替换为Category==5行的Value值
目前仅能提取指定Date和Location下Category=5的Value值:
df.loc[(df['Date'] == 20220101) & (df['Location'] == 'FE') & (df['Category'] == 5), 'Value'].iloc[0]
需要一个简便高效的方法实现批量修改Value列值。
可复现代码
df = pd.DataFrame({ 'Date':[20220101, 20220101, 20220101, 20220101, 20220101, 20220101, 20220101, 20220101, 20220102, 20220102, 20220102, 20220102, 20220102, 20220102, 20220102, 20220102], 'Location':['FE', 'FE', 'FE', 'FE', 'FE', 'FE', 'RP', 'RP', 'FE', 'FE', 'FE', 'FE', 'FE', 'FE', 'RP', 'RP'], 'Category':[1, 2, 3, 4, 5, 6, 5, 6, 1, 2, 3, 4, 5, 6, 5, 6], 'Value':[0.23, 0.24, 0.26, 0.27, 0.28, 0.3, 0.32, 0.35, 0.2, 0.23, 0.25, 0.26, 0.28, 0.32, 0.34, 0.36] })
解决方案
以下是几种高效的批量实现方法:
方法一:分组映射替换
先提取每组Category=5的Value作为映射,再匹配替换目标行:
# 生成(Date, Location)到对应Category=5的Value的映射 grouped_map = df[df['Category'] == 5].set_index(['Date', 'Location'])['Value'] # 筛选出Category>=5的行,通过索引匹配映射值完成替换 mask = df['Category'] >= 5 df.loc[mask, 'Value'] = df.loc[mask].set_index(['Date', 'Location']).index.map(grouped_map.get)
方法二:groupby+apply分组处理
通过分组应用自定义函数,直接修改每组内的目标值:
def process_group(group): # 获取当前组Category=5的Value cat5_val = group.loc[group['Category'] == 5, 'Value'].iloc[0] # 替换组内Category>=5的行的Value group.loc[group['Category'] >= 5, 'Value'] = cat5_val return group # 按Date和Location分组应用函数 df_new = df.groupby(['Date', 'Location']).apply(process_group).reset_index(drop=True)
方法三:transform广播替换
利用transform将每组Category=5的Value广播到整组,再通过条件替换:
# 对每组,获取Category=5的Value并广播到组内所有行 cat5_broadcast = df.groupby(['Date', 'Location'])['Value'].transform( lambda x: x[df['Category'] == 5].iloc[0] ) # 替换Category>=5的行的Value df['Value'] = df.apply( lambda row: cat5_broadcast[row.name] if row['Category'] >=5 else row['Value'], axis=1 )
执行任意一种方法后,DataFrame都会符合期望的输出结果。
内容的提问来源于stack exchange,提问作者fjurt
相关产品推荐
相关产品推荐

