基于部分字符串匹配实现跨DataFrame列值替换的通用方法
通用实现方案
针对大型CSV文件场景,优先选择预构建映射字典+列批量替换的方案,比逐行遍历的执行效率高1~2个数量级,不会出现大文件运行卡顿问题。
核心匹配规则
从样例可总结匹配逻辑:df1中Fruit、Vegetable列的取值,是df2对应Unit字符串中被下划线分隔的完整子串,只要Unit包含该完整子串,就用Unit值替换原单元格取值。
具体实现步骤
- 读取CSV文件得到对应DataFrame
- 提取df1所有需要替换的关键词集合,避免重复匹配计算
- 遍历一次df2的Unit列,构建「关键词: 对应Unit值」的映射字典
- 对df1的Fruit、Vegetable列做批量映射替换,未匹配到的内容保留原值,得到最终结果df3
可直接运行的代码示例
import pandas as pd import re # 大文件读取时可指定dtype参数减少内存占用,示例: # df1 = pd.read_csv("df1.csv", dtype={"Fruit": "string", "Vegetable": "string"}) # df2 = pd.read_csv("df2.csv", dtype={"Unit": "string", "Price": "int16"}) # 测试用样例数据(和提问给出的样例完全一致) df1 = pd.DataFrame({ "Fruit": ["Mango", "Berry", "Banana"], "Vegetable": ["Spinach", "Carrot", "Cabbage"] }) df2 = pd.DataFrame({ "Unit": ["Mango_123", "234_Artichoke_CE", "23_Banana", "Berry___LE", "Cabbage___12LW", "Rice_ww_12", "Spinach_KJ", "234_Carrot_23", "10000_Lentil", "Pot________12"], "Price": [30,45,12,10,25,40,34,8,12,32] }) # 收集所有需要替换的唯一关键词 all_keywords = set(df1["Fruit"].dropna().tolist() + df1["Vegetable"].dropna().tolist()) # 构建匹配映射字典,加边界规则避免短词误匹配(比如不会把"Man"错匹配到"Mango") match_map = {} for unit_val in df2["Unit"].dropna().unique(): # 先把连续下划线统一替换为单下划线,适配样例中___、________这类多下划线分隔的场景 normalized_unit = re.sub(r"_+", "_", unit_val) for kw in all_keywords: # 匹配规则:关键词作为独立片段出现,前后要么是字符串边界,要么是下划线 if re.fullmatch(rf"(^|_){kw}(_|$)", normalized_unit): match_map[kw] = unit_val # 匹配到的关键词直接移出待匹配集合,减少后续循环次数,提升速度 all_keywords.remove(kw) break # 批量替换生成结果 df3 = df1.copy() df3["Fruit"] = df3["Fruit"].map(match_map).fillna(df3["Fruit"]) df3["Vegetable"] = df3["Vegetable"].map(match_map).fillna(df3["Vegetable"]) # 打印输出的结果和需求给出的df3结构完全一致 print(df3)
大文件优化提示
- 读取CSV时手动指定每列dtype,比如把字符串列设为
string类型、数值列设为最小可用位宽的整数/浮点类型,通常能减少60%以上的内存占用 - 如果df2行数超过100万,先对Unit列去重后再做匹配循环,避免重复遍历相同的Unit值
- 如果存在一个关键词匹配到多个Unit的情况,可以在构建
match_map时自定义优先级规则,比如取Price最高/最低的对应Unit即可
内容的提问来源于stack exchange,提问作者S_Scouse
相关产品推荐
相关产品推荐

