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

如何高效实现Pandas DataFrame中列表的两两对比并生成叉积矩阵?

问题描述

给定如下包含列表类型列的DataFrame:

import pandas as pd

df = pd.DataFrame({'Ind':['A','B','C','D'],'lists':[['dog','cat','horse','squirrel','bird'],
                       ['dog','horse','fish','whale'],
                       ['moose','cat','squirrel','ant','chicken'],
                       ['dog','moose','cat','bird','ant']]})

需要生成一个对称的相似度矩阵,其中元素规则为:

  • 列表完全相同时值为0
  • 无共同元素时值为1
  • 计算公式:(min(len(list1), len(list2)) - 共同元素数量) / min(len(list1), len(list2))

当前使用双重循环实现需求,但数据规模增大时性能不足。已知矩阵是对称的,希望通过减少计算次数(仅计算N*(N+1)/2次而非N²次)来优化,同时保持输出与原结果一致。

原循环实现代码:

list_tot = []
for i in range(len(df)):
    list_temp = []
    for j in range(len(df)):
        list1 = df.iloc[i]['lists']
        list2 = df.iloc[j]['lists']
        minlist = min(len(list1),len(list2))
        dis = (minlist - len([el for el in list1 if el in list2]))/minlist
        list_temp.append(dis)
    list_tot.append(list_temp)

原输出结果:

[[0.0, 0.5, 0.6, 0.4],
[0.5, 0.0, 1.0, 0.75],
[0.6, 1.0, 0.0, 0.4],
[0.4, 0.75, 0.4, 0.0]]

优化方案

1. 用集合优化交集计算效率

原代码中通过列表推导式找共同元素的效率较低,先将所有列表转为集合,利用集合的快速交集操作提升性能:

df['sets'] = df['lists'].apply(set)

2. 利用对称性减少计算量

由于矩阵是对称的(matrix[i][j] = matrix[j][i]),且对角线元素恒为0,只需计算上三角(含对角线)的元素,再填充对称位置即可,计算量直接减半:

n = len(df)
# 初始化全0矩阵
result = [[0.0]*n for _ in range(n)]

for i in range(n):
    set_i = df['sets'].iloc[i]
    len_i = len(df['lists'].iloc[i])
    # 仅计算j >= i的部分
    for j in range(i, n):
        set_j = df['sets'].iloc[j]
        len_j = len(df['lists'].iloc[j])
        min_len = min(len_i, len_j)
        common_count = len(set_i & set_j)
        distance = (min_len - common_count) / min_len
        result[i][j] = distance
        # 对称位置赋值(跳过对角线)
        if i != j:
            result[j][i] = distance

3. 更简洁的迭代器实现(适用于大规模数据)

使用itertools.combinations_with_replacement生成所有i<=j的索引对,写法更简洁且底层实现更高效:

import itertools

n = len(df)
result = [[0.0]*n for _ in range(n)]

# 遍历所有i<=j的索引组合
for i, j in itertools.combinations_with_replacement(range(n), 2):
    set_i = df['sets'].iloc[i]
    set_j = df['sets'].iloc[j]
    len_i = len(df['lists'].iloc[i])
    len_j = len(df['lists'].iloc[j])
    min_len = min(len_i, len_j)
    common_count = len(set_i & set_j)
    distance = (min_len - common_count) / min_len
    result[i][j] = distance
    if i != j:
        result[j][i] = distance

验证结果

运行上述优化代码后,输出与原循环结果完全一致:

[[0.0, 0.5, 0.6, 0.4],
[0.5, 0.0, 1.0, 0.75],
[0.6, 1.0, 0.0, 0.4],
[0.4, 0.75, 0.4, 0.0]]

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 08:35:30