Pandas中如何基于映射表批量替换DataFrame多列对应值
多列联动匹配替换实现方案
你遇到的是多列联合作为唯一键的映射替换场景,单列replace只支持单键单值/多值映射,没法直接处理三列组合匹配的需求,下面两种方法都能实现预期效果,优先选第一种:
方法1:merge左连接(推荐,性能好、逻辑稳定)
核心思路是把df2和映射参照表df1按照三个_a后缀的列做左连接,直接拉取匹配到的_b后缀列的值,再重命名为原列名即可,不会出现逐行遍历的性能问题,数据量大的时候优势很明显。
import pandas as pd # 构造示例数据(实际使用时跳过这步,直接读取自己的df1、df2即可) df1 = pd.DataFrame({ 'id1_a': ['a1', 'aa1', 'ac1'], 'id2_a': ['a2', 'a2', 'c2'], 'id3_a': ['a3', 'a3', 'a3'], 'id1_b': ['b1', 'b12', 'bc2'], 'id2_b': ['b2', 'b22', 'bc2'], 'id3_b': ['b3', 'b23', 'bc3'] }) df2 = pd.DataFrame({ 'id1_a': ['a1', 'a1', 'aa1', 'ac1'], 'id2_a': ['a2', 'a2', 'a2', 'c2'], 'id3_a': ['a3', 'a3', 'a3', 'a3'] }) # 执行匹配替换 result = df2.merge( right=df1, on=['id1_a', 'id2_a', 'id3_a'], # 指定三列为联合匹配键 how='left' # 保留df2全部行,匹配不到的位置会自动填充空值 )[['id1_b', 'id2_b', 'id3_b']].rename(columns={ 'id1_b': 'id1_a', 'id2_b': 'id2_a', 'id3_b': 'id3_a' })
运行后得到的result和你给出的预期结果完全一致。后续如果要增减匹配列、映射列,只要修改on参数和最后选取的列名即可,维护成本很低。
方法2:元组键字典映射(适合小体量数据)
如果你想沿用单值映射的字典思路,可以把三列的行值拼成元组作为字典键,对应的映射结果也拼成元组作为值,再逐行匹配替换:
# 构建联合键映射字典 mapping = dict(zip( zip(df1['id1_a'], df1['id2_a'], df1['id3_a']), zip(df1['id1_b'], df1['id2_b'], df1['id3_b']) )) # 逐行替换 df2[['id1_a', 'id2_a', 'id3_a']] = df2.apply( lambda row: mapping.get((row['id1_a'], row['id2_a'], row['id3_a']), (None, None, None)), axis=1, result_type='expand' )
这个方法在数据量超过10万行的时候,apply逐行遍历的速度会明显比merge慢,只建议小数据集场景用。
注意:使用前先确认df1中三个匹配列的组合是唯一的,如果存在重复的三列值组合,merge会返回多行匹配结果,导致最终结果行数超过df2原行数。
内容的提问来源于stack exchange,提问作者gh1222
相关产品推荐
相关产品推荐

