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

如何比较两个Pandas数据框中的列表列,提取共同元素?

问题

需要对比df2中set_1和set_2列的列表,与df1中ins列的列表,找出所有共同元素。目前仅能实现单行单列的比较,不知道如何对两个数据框的所有行进行比较以得到目标结果。

现有单行比较代码:

import pandas as pd

d1 = {'chr': [1, 1], 'start': [64, 1000], 'end': [150, 2000], 'family': ['a', 'b'],
      'ins': [['P1-12', 'P1-22', 'P1-25', 'P1-28', 'P1-90'],
              ['P1-6', 'P1-89', 'P1-92', 'P1-93']]}

df1 = pd.DataFrame.from_dict(data=d1)

d2 = {'set_1': [['P1-12', 'P1-25', 'P1-28'], ['P1-6', 'P1-89', 'P1-93']],
      'set_2': [['P1-89', 'P1-92', 'P1-93'], ['P1-25', 'P1-28', 'P1-90']]}

df2 = pd.DataFrame.from_dict(data=d2)

matches = [x for x in df2.iloc[0, 0] if x in df1.iloc[0, 4]]

输入数据(原始数据df1约13k行,df2约90行):
df1:

chr  start   end family                                  ins
0    1     64   150      a  [P1-12, P1-22, P1-25, P1-28, P1-90]
1    1   1000  2000      b          [P1-6, P1-89, P1-92, P1-93]

df2:

set_1                  set_2
0  [P1-12, P1-25, P1-28]  [P1-89, P1-92, P1-93]
1   [P1-6, P1-89, P1-93]  [P1-25, P1-28, P1-90]

期望输出:

chr  start   end family  df2_index               ins_set1               ins_set2
0    1     64   150      a          0  [P1-12, P1-25, P1-28]                     []
1    1     64   150      a          1                     []  [P1-25, P1-28, P1-90]
2    1   1000  2000      b          0                     []  [P1-89, P1-92, P1-93]
3    1   1000  2000      b          1   [P1-6, P1-89, P1-93]                     []

解决方案

要实现所有行的交叉比较,核心是先构建df1和df2的笛卡尔积(即每一行df1对应所有df2的行),再逐行计算交集。具体步骤如下:

  1. 给df2添加索引列df2_index,方便后续关联;
  2. 用merge生成两个数据框的笛卡尔积(通过指定一个共同的临时列);
  3. 定义函数计算两个列表的交集;
  4. 分别计算ins与set_1、ins与set_2的交集,生成ins_set1和ins_set2列;
  5. 整理输出格式,去掉临时列。

完整代码:

import pandas as pd

# 初始化数据框
d1 = {'chr': [1, 1], 'start': [64, 1000], 'end': [150, 2000], 'family': ['a', 'b'],
      'ins': [['P1-12', 'P1-22', 'P1-25', 'P1-28', 'P1-90'],
              ['P1-6', 'P1-89', 'P1-92', 'P1-93']]}
df1 = pd.DataFrame.from_dict(data=d1)

d2 = {'set_1': [['P1-12', 'P1-25', 'P1-28'], ['P1-6', 'P1-89', 'P1-93']],
      'set_2': [['P1-89', 'P1-92', 'P1-93'], ['P1-25', 'P1-28', 'P1-90']]}
df2 = pd.DataFrame.from_dict(data=d2).reset_index(names='df2_index')

# 定义交集计算函数
def get_intersection(list1, list2):
    return list(set(list1) & set(list2))

# 生成笛卡尔积
df1['key'] = 1
df2['key'] = 1
merged = pd.merge(df1, df2, on='key').drop('key', axis=1)

# 计算交集列
merged['ins_set1'] = merged.apply(lambda row: get_intersection(row['ins'], row['set_1']), axis=1)
merged['ins_set2'] = merged.apply(lambda row: get_intersection(row['ins'], row['set_2']), axis=1)

# 整理输出格式
result = merged[['chr', 'start', 'end', 'family', 'df2_index', 'ins_set1', 'ins_set2']]
print(result)

运行后输出与期望一致。考虑到df1有13k行、df2有90行,笛卡尔积会生成117万行数据,apply逐行计算可能稍慢,若要优化可以把列表转为集合提前存储,减少重复计算:

# 提前把ins列转为集合
df1['ins_set'] = df1['ins'].apply(set)

# 修改交集函数
def get_intersection_fast(set1, list2):
    return list(set1 & set(list2))

# 计算交集时用提前转好的集合
merged['ins_set1'] = merged.apply(lambda row: get_intersection_fast(row['ins_set'], row['set_1']), axis=1)
merged['ins_set2'] = merged.apply(lambda row: get_intersection_fast(row['ins_set'], row['set_2']), axis=1)

这样能减少每次计算时重复转集合的开销,提升处理速度。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 11:14:55