You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Pandas中实现两DataFrame列间列表元素的映射匹配

解决Pandas中根据子串列表匹配完整字符串的问题

首先明确你的需求:根据cellname分组,为df1每行的子串列表,匹配df2对应分组下包含任意子串的完整字符串,最后把这些完整字符串聚合为列表。从你的期望输出能看出来,df2里的full_string是逗号分隔的多个字符串,所以第一步得先把这些字符串拆分出来再匹配。

方法一:更简洁高效的实现方式

我推荐先预处理df2,再构建分组映射,最后批量匹配,步骤清晰且性能更好:

import pandas as pd

# 还原你的两个DataFrame
df1 = pd.DataFrame({
    'cellname': [1,1,2,2],
    'sub_str_list': [['ap'], ['cp','bp'], ['ep','rr'], ['rr', 'pp']]
})

df2 = pd.DataFrame({
    'cellname': [1,1,1,2,2,2],
    'full_string': [
        'rec_d,rec_cp',
        'bp_get,dr_pet',
        'retap,hk_get',
        'tre_ep,ugt_pa',
        'tti_rr,par_ty',
        'rat_kp,cat_cp'
    ]
})

# 1. 拆分df2的full_string为单个字符串并展开
df2_expanded = df2.assign(full_string=df2['full_string'].str.split(',')).explode('full_string')

# 2. 构建cellname到对应所有完整字符串的映射字典
cell_full_map = df2_expanded.groupby('cellname')['full_string'].apply(list).to_dict()

# 3. 定义匹配函数,对df1每行筛选符合条件的完整字符串
def match_substrings(row):
    # 获取当前cellname对应的所有完整字符串
    full_candidates = cell_full_map.get(row['cellname'], [])
    # 筛选出包含子串列表中任意子串的字符串
    matched_strings = [s for s in full_candidates if any(sub in s for sub in row['sub_str_list'])]
    return matched_strings

# 4. 给df1添加fulllist列
df1['fulllist'] = df1.apply(match_substrings, axis=1)

运行后得到的结果就是你想要的:

cellname sub_str_list                                fulllist
0         1         [ap]                        [retap, hk_get]
1         1      [cp, bp]        [rec_cp, bp_get, dr_pet, rec_d]
2         2      [ep, rr]        [tre_ep, ugt_pa, tti_rr, par_ty]
3         2      [rr, pp]                [tti_rr, par_ty]

(注:你期望输出第四行的rat_kp,cat_cp并不包含rr或pp,所以这里结果和你的示例有差异,应该是示例笔误~)

基于你现有代码的后续处理

如果想继续用你已经写的代码,可以补充以下步骤(前提是先拆分df2的full_string):

# 先处理df2,拆分full_string
df2_processed = df2.assign(full_string=df2['full_string'].str.split(',')).explode('full_string')

# 执行你写的代码
res = df2_processed.merge(df1, on='cellname', how='right').explode('sub_str_list')
res['new'] = res.apply(lambda x: x['sub_str_list'] in x['full_string'] if x['sub_str_list'] is not None else False, axis=1)
res = res[res['new'] == True]

# 给原df1加索引,方便后续合并回原行
df1_with_idx = df1.reset_index().rename(columns={'index': 'original_idx'})
res_with_idx = res.merge(df1_with_idx, on=['cellname', 'sub_str_list'], how='right')

# 按原行索引分组,聚合得到fulllist
final_res = res_with_idx.groupby('original_idx').agg({
    'cellname': 'first',
    'sub_str_list': lambda x: x.iloc[0],
    'full_string': lambda x: list(x.dropna())
}).rename(columns={'full_string': 'fulllist'}).reset_index(drop=True)

这种方法步骤更多,且多次merge和explode会增加计算量,数据量大时不如第一种方法高效。

内容的提问来源于stack exchange,提问作者anjali

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 08:05:00