优化含类JSON列的DataFrame合并与精准去重方案问询
Pandas DataFrame合并优化方案
问题描述
现有数据
import pandas as pd df1 = pd.DataFrame({ "name": ["cream", "hello"], "keywords": ["[pudding, heavy Cream, heavycream, Sourcream]", "[hello, world, hi]"] }) df2 = pd.DataFrame({ "ingredient": ["cream", "hi", "MS"], "Frequency": [5, 10, 23] })
合并需求
生成新的DataFrame需满足:
- 完整保留
df1的所有数据; - 仅当
df2的ingredient值既未精准匹配df1的name字段值,也未精准匹配df1的keywords字段中的任意元素时,才将该ingredient以name=该值、keywords为空的形式添加进去(注意:大小写不同视为不同值,例如'cream'和'heavy Cream'是两个独立值)。
当前代码问题
现有代码首次运行能得到预期结果,但多次执行会出现反斜杠异常,且循环嵌套+多次concat导致运行效率低下。原代码如下:
df_new = df1.copy() for ingredient in df2["ingredient"].str.lower(): if df1["name"].str.contains(ingredient).any(): df1 = df1.loc[~df1["name"].str.contains(ingredient)] else: df1["keywords"] = df1["keywords"].astype('str') df1["keywords"] = df1["keywords"].apply(lambda x: x[1:-1].split(", ")) for keyword in df1["keywords"]: print(ingredient) print(keyword) if ingredient not in keyword: print("add value") df_new = pd.concat([df_new, pd.DataFrame({"name": ingredient, "keywords": ""},index=[0])], ignore_index=True)
优化实现
核心思路
- 一次性解析
df1的keywords字段,将字符串格式的列表转为实际列表,避免重复修改数据引发的格式异常; - 提前收集所有需要排除的匹配项(
df1的name集合 + 所有keywords元素集合),集合查询的效率远高于循环判断; - 批量筛选
df2中符合条件的ingredient,一次性合并到结果中,避免多次concat带来的性能损耗。
优化代码
import pandas as pd # 初始化原始数据 df1 = pd.DataFrame({ "name": ["cream", "hello"], "keywords": ["[pudding, heavy Cream, heavycream, Sourcream]", "[hello, world, hi]"] }) df2 = pd.DataFrame({ "ingredient": ["cream", "hi", "MS"], "Frequency": [5, 10, 23] }) # 解析keywords字段:将字符串转为实际列表(处理前后括号和逗号分隔) df1['keywords'] = df1['keywords'].apply(lambda x: [item.strip() for item in x.strip('[]').split(',')]) # 构建需要排除的匹配项集合(精准匹配,保留原大小写) exclude_names = set(df1['name']) exclude_keywords = set() for kw_list in df1['keywords']: exclude_keywords.update(kw_list) exclude_all = exclude_names.union(exclude_keywords) # 筛选df2中符合添加条件的ingredient new_entries = df2[~df2['ingredient'].isin(exclude_all)][['ingredient']].rename(columns={'ingredient': 'name'}) new_entries['keywords'] = "" # 合并得到最终结果 df_new = pd.concat([df1, new_entries], ignore_index=True) # 输出结果 print(df_new)
代码效果
运行后得到的df_new符合需求:
name keywords 0 cream [pudding, heavy Cream, heavycream, Sourcream] 1 hello [hello, world, hi] 2 MS
内容的提问来源于stack exchange,提问作者Vineet
相关产品推荐
相关产品推荐

