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

如何更优雅地计算含列表的Pandas Series间的相似度矩阵?

嘿,我明白你现在的需求——用嵌套map虽然能算出这个相似度矩阵,但总觉得不够优雅对吧?这里有几个更简洁高效的实现方式,你可以试试看:

方法1:借助scipy.spatial.distance.cdist(高效推荐)

Scipy的cdist是专门用来计算两两样本间距离/相似度的工具,底层做了优化,比手动嵌套map效率高很多,尤其适合数据量较大的场景。我们可以直接把自定义的相似度度量函数传进去:

import pandas as pd
import numpy as np
from scipy.spatial.distance import cdist

# 你的原始数据
a = pd.Series([[1,2,34], [2,3], [2,3,4,5,1]], index = [1,2,3])
def metric(x, y): return len(np.intersect1d(x, y))

# 将Series转为numpy数组格式
arr = a.to_numpy()
# 计算两两相似度矩阵
sim_matrix = cdist(arr, arr, metric=metric)
# 转为带索引的DataFrame
sim_df = pd.DataFrame(sim_matrix, index=a.index, columns=a.index)
方法2:用标准库itertools.product生成配对

如果不想引入Scipy依赖,用Python标准库的itertools.product生成所有索引对,再批量计算相似度,代码可读性很强:

import pandas as pd
import numpy as np
import itertools

a = pd.Series([[1,2,34], [2,3], [2,3,4,5,1]], index = [1,2,3])
def metric(x, y): return len(np.intersect1d(x, y))

# 生成所有索引的笛卡尔积配对
index_pairs = list(itertools.product(a.index, repeat=2))
# 批量计算每对的相似度
similarities = [metric(a[i], a[j]) for i, j in index_pairs]
# 重塑为矩阵并转为DataFrame
sim_df = pd.DataFrame(
    np.array(similarities).reshape(len(a), len(a)),
    index=a.index,
    columns=a.index
)
方法3:利用集合操作优化(简洁高效)

因为你的元素都是可哈希的数字,把每个列表转成集合后,用集合的交集操作&会比np.intersect1d更快,代码也更简洁:

import pandas as pd
import numpy as np

a = pd.Series([[1,2,34], [2,3], [2,3,4,5,1]], index = [1,2,3])

# 将每个列表转为集合
set_series = a.apply(set)
# 用列表推导式计算两两交集长度
sim_matrix = np.array([[len(s1 & s2) for s2 in set_series] for s1 in set_series])
sim_df = pd.DataFrame(sim_matrix, index=a.index, columns=a.index)

这几种方法都比嵌套map更优雅,其中方法1和方法3在数据量增大时的性能优势会更明显。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 09:12:10