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

求Numpy优化方案:快速计算8000×8000数据框行对的Weighted Jaccard距离

大尺寸DataFrame加权Jaccard距离的Numpy优化方案

问题背景

需要计算8000×8000的Pandas数据框中每一对行的加权Jaccard距离,原有的双重循环实现(基于iterrows迭代)速度极慢,需通过Numpy向量化计算优化。

原方案的核心问题

双重循环(尤其是iterrows行迭代)属于Python级别的逐次操作,8000行数据需计算约3200万次行对,循环本身的开销会导致计算效率极低;同时每次调用函数处理单行数据,进一步增加了额外开销。

优化思路

利用Numpy的向量化计算和广播机制,将所有行对的计算一次性完成,避免Python循环的开销;同时通过数学变换减少内存占用,适配大尺寸数据:

  • 利用公式转换:min(a,b) = (a+b - |a-b|)/2、max(a,b) = (a+b + |a-b|)/2,将行对的min/max总和转换为行总和与元素差绝对值总和的组合计算,避免生成超大三维数组。

完整优化代码

import pandas as pd
import numpy as np

# 替换为你的8000×8000数据框
matrix = pd.DataFrame([[1, 2 ,3],
                       [2, 1, 1],
                       [3, 1, 1]])
arr = matrix.values  # 将DataFrame转为Numpy数组,减少Pandas迭代开销
n_rows = arr.shape[0]

# 1. 计算每行的元素总和
row_sums = arr.sum(axis=1)

# 2. 计算所有行对的sum(a) + sum(b),利用广播生成(n_rows, n_rows)矩阵
sum_ab = row_sums[:, np.newaxis] + row_sums

# 3. 计算所有行对的元素差的绝对值之和,广播后按列求和得到(n_rows, n_rows)矩阵
abs_diff_sum = np.abs(arr[:, None, :] - arr[None, :, :]).sum(axis=2)

# 4. 推导每对行的min总和与max总和
sum_min = (sum_ab - abs_diff_sum) / 2
sum_max = (sum_ab + abs_diff_sum) / 2

# 5. 生成加权Jaccard相似度矩阵(若需距离则计算 1 - weighted_jaccard_sim)
weighted_jaccard_sim = sum_min / sum_max

# 6. 提取上三角部分(仅保留i<j的行对结果,避免重复计算)
upper_triangle_results = weighted_jaccard_sim[np.triu_indices(n_rows, k=1)]

关键说明

  1. 内存优化:通过数学转换,仅生成(8000,8000)的中间数组,内存占用约512MB(float64类型),完全适配常规机器内存。
  2. 速度提升:所有计算均为Numpy底层C实现的向量化操作,比Python循环快几个数量级,8000行的计算可在合理时间内完成。
  3. 结果提取:np.triu_indices(n_rows, k=1)用于获取上三角索引,仅保留未重复的行对结果,与原循环中other_index>index的逻辑一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 15:53:09