基于列表列包含操作的Pandas数据匹配关联问题求助
问题描述
现有两个Pandas DataFrame:
import pandas as pd multi_df = pd.DataFrame({'multi_project_ID': ["Combo_1","Combo_2","Combo_3","Combo_4"], 'multi_items':[['Chips','Biscuits','Chocolates'],['Alcoholic Drinks','Juices','Fruits'],['Plants','Veggies','Chips'],['Cars']], 'multi_labels':[[1,2,3],[4,5,6],[8,9,10],[11]]}) single_df = pd.DataFrame({'single_project_ID': ["ABC_1","DEF_2","JKL_3","MNO_3"], 'single_items':[['Chips'],['Alcoholic Drinks'],['Biscuits'],['Smoking']], 'single_labels':[[1],[4],[8],[9]]})
需实现以下需求:
- 检查
single_df中single_items列表的元素是否存在于multi_df的multi_items列表中; - 若存在匹配项,提取对应匹配项的
multi_project_ID和multi_labels; - 若无匹配项,则填充NA。
尝试了以下代码但无法实现需求:
print(single_df.groupby('single_labels').sum()['single_items'].apply(lambda x: list(set(x))).reset_index())
预期输出:
| single_project_ID | single_items | single_labels | multi_project_ID | multi_labels |
|---|---|---|---|---|
| ABC_1 | ['Chips'] | [1] | Combo_1, Combo_3 | [1,2,3], [8,9,10] |
| DEF_2 | ['Alcoholic Drinks'] | [4] | Combo_2 | [4,5,6] |
| JKL_3 | ['Biscuits'] | [8] | Combo_1 | [1,2,3] |
| MNO_3 | ['Smoking'] | [9] | NaN | NaN |
解决方法
通过展开列表元素建立匹配关系,再聚合还原的方式实现需求,具体代码如下:
import pandas as pd # 1. 展开multi_df的列表列,让每个元素对应一行 multi_expanded = multi_df.explode('multi_items').reset_index(drop=True) # 同步展开multi_labels,保证和multi_items的行对应 multi_expanded['label'] = multi_expanded['multi_labels'].explode() # 2. 展开single_df的列表列 single_expanded = single_df.explode(['single_items', 'single_labels']).reset_index(drop=True) # 3. 按物品名称匹配,合并两个数据集 merged = single_expanded.merge( multi_expanded[['multi_items', 'multi_project_ID', 'multi_labels']], left_on='single_items', right_on='multi_items', how='left' ) # 4. 按single_project_ID聚合,还原列表并整理匹配结果 result = merged.groupby('single_project_ID').agg({ 'single_items': lambda x: list(set(x)), 'single_labels': lambda x: list(set(map(int, x))), 'multi_project_ID': lambda x: ','.join(x.dropna().unique()) if not x.dropna().empty else pd.NA, 'multi_labels': lambda x: ','.join(map(str, x.dropna().unique())) if not x.dropna().empty else pd.NA }).reset_index() # 调整列顺序与预期输出一致 result = result[['single_project_ID', 'single_items', 'single_labels', 'multi_project_ID', 'multi_labels']] print(result)
代码说明
- 展开列表:用
explode将嵌套列表拆分为单行,把复杂的列表匹配转化为单元素匹配,降低逻辑复杂度; - 合并匹配:通过
merge的左连接方式,保留single_df所有行,同时匹配multi_df中对应的项目信息; - 聚合还原:按项目ID分组,将匹配到的多个项目ID和标签合并为字符串(若需保留列表格式,可修改聚合逻辑为
lambda x: list(x.dropna().unique())),无匹配项时填充pd.NA; - 格式调整:最后调整列顺序,和预期输出对齐。
内容的提问来源于stack exchange,提问作者The Great
相关产品推荐
相关产品推荐

