Pandas匹配两DataFrame标签ID 映射活动名称及解析报错解决
解决方案
报错根因
ast.literal_eval仅支持解析符合Python语法的字符串格式输入,传入0、NaN、None这类非字符串异常值时会直接触发ValueError: malformed node or string报错,和你的推测一致。
另外不需要将标签拆分为独立列做合并,拆列会引入列数动态变化、多轮合并效率低的问题,直接构建ID映射逐行转换是更稳定的实现方式。
完整实现代码
1. 安全解析tags字段,兼容异常值
先编写容错解析函数,跳过所有非合法格式的取值,从根源避免解析报错:
import ast import pandas as pd import numpy as np def safe_parse_tags(tag_input): # 直接拦截0、空值、NaN类异常输入,返回空列表 if pd.isna(tag_input) or tag_input == 0: return [] # 仅对字符串类型输入做格式解析 if isinstance(tag_input, str): try: parse_res = ast.literal_eval(tag_input) # 解析结果非列表的脏数据统一返回空列表 return parse_res if isinstance(parse_res, list) else [] except: # 格式错误无法解析的脏数据直接返回空列表 return [] return [] # 替换为你实际的tags列名,示例中列名为tags df1["parsed_tags"] = df1["tags"].apply(safe_parse_tags)
2. 构建标签ID到活动名的映射字典
利用字典做映射匹配,效率远高于多轮merge,也不需要处理不定长标签列的问题:
# 先对标签映射表去重,避免同ID多值冲突,再转为ID->活动名的字典 tag2campaign = df2.drop_duplicates(subset=["Tags"]).set_index("Tags")["Campaigns"].to_dict()
注意:如果匹配时出现ID对不上的问题,先统一两边ID的类型,比如执行
df2["Tags"] = df2["Tags"].astype(str)把ID统一转成字符串,后续提取DF1标签ID时也转成相同类型即可。
3. 标签匹配与结果拼接
逐行将解析后的标签ID替换为对应活动名,最终拼接为逗号分隔的字符串:
def tags_to_campaign_str(tag_list, id_map, miss_placeholder=""): # 提取标签ID:如果tags是字典列表,把下面代码里的"id"替换为你实际存储标签ID的字典键(比如tagId、tag_id等) # 如果tags是直接存ID的列表,就用tag_ids = [t for t in tag_list] tag_ids = [t.get("id") for t in tag_list if isinstance(t, dict)] # 匹配活动名,过滤无匹配结果的项 matched_campaigns = [ str(id_map.get(tid, miss_placeholder)) for tid in tag_ids if tid in id_map ] # 拼接为逗号分隔字符串 return ",".join([c for c in matched_campaigns if c]) # 生成最终结果列 df1["tag_campaigns"] = df1["parsed_tags"].apply(lambda x: tags_to_campaign_str(x, tag2campaign))
方案优势
- 全链路加了异常兜底,0、NaN、格式错误的脏数据不会中断任务,会统一处理为空字符串
- 不需要拆分不定长标签为独立列,避免列数动态变化的适配问题,单轮遍历即可完成匹配,性能远高于拆列合并的方案
- 可灵活配置无匹配标签的兜底值,适配不同数据清洗需求
内容的提问来源于stack exchange,提问作者Hamza Ahmed
相关产品推荐
相关产品推荐

