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

Pandas多DataFrame遍历计算相似词数速度慢,求优化方案

哇,10k×3k的双重循环确实会慢到让人崩溃——3000万次Python级别的迭代,单线程扛不住太正常了。我来给你几个实打实的优化方案,从简单到进阶都有,保证能把速度提上去几个数量级!

先说说原代码慢的核心原因

  1. 双重Python循环:Python的for循环本身就比底层语言慢,嵌套循环直接把复杂度拉到O(N*M),3000万次重复操作肯定卡。
  2. 重复的集合转换:每次循环都把text_tokenized的列表转成集合,完全是做无用功——这些转换只需要做一次就行。
  3. 低效的DataFrame构建:逐行创建字典再拼接小DataFrame,pandas每次拼接都要重新分配内存,开销极大。

方案1:预转换集合 + 列表推导式(快速见效,代码改动小)

先把两个DataFrame的所有行都预转成集合,然后用列表推导式替代嵌套循环——列表推导式是Python层面最接近底层速度的循环方式。

import pandas as pd

# 预转换所有tokenized文本为集合,只做一次!
set_list1 = data['text_tokenized'].apply(set).tolist()
set_list2 = data2['text_tokenized'].apply(set).tolist()
codes = data['code'].tolist()

# 用列表推导式计算相似度矩阵,比嵌套for循环快N倍
similarity_matrix = [[len(s1 & s2) for s2 in set_list2] for s1 in set_list1]

# 一次性生成结果DataFrame,避免逐行拼接
result_df = pd.DataFrame(
    similarity_matrix,
    columns=[f"df2_row_{idx}" for idx in range(len(set_list2))]
)
result_df['code'] = codes
# 把code列放到最前面
result_df = result_df[['code'] + result_df.columns[:-1].tolist()]

这个方案至少能把速度提升5-10倍,因为预转换避免了重复计算,列表推导式比嵌套循环高效得多。


方案2:CountVectorizer + 矩阵点积(速度天花板,适合大数据)

如果想追求极致速度,就用向量化运算——把文本转换成布尔矩阵,然后用numpy的点积计算交集数量(二进制矩阵的点积就是两个向量共同词的数量)。这种方法用的是C底层运算,速度比Python循环快几十甚至上百倍。

import pandas as pd
from sklearn.feature_extraction.text import CountVectorizer

# 把tokenized列表转成空格分隔的字符串(CountVectorizer需要输入字符串)
data_texts = data['text_tokenized'].apply(lambda x: ' '.join(x))
data2_texts = data2['text_tokenized'].apply(lambda x: ' '.join(x))

# 初始化二进制CountVectorizer:每个词出现标记为1,不统计出现次数
vec = CountVectorizer(binary=True)
# 拟合所有文本,得到统一的词汇表
all_texts = pd.concat([data_texts, data2_texts])
vec.fit(all_texts)

# 转换为布尔矩阵(形状分别是(10000, 词汇量)和(3000, 词汇量))
data_matrix = vec.transform(data_texts).toarray()
data2_matrix = vec.transform(data2_texts).toarray()

# 矩阵点积直接得到相似度矩阵(每个元素就是相似词的数量)
similarity_matrix = data_matrix @ data2_matrix.T

# 生成结果DataFrame
result_df = pd.DataFrame(
    similarity_matrix,
    columns=[f"df2_row_{idx}" for idx in range(data2.shape[0])]
)
result_df['code'] = data['code'].values
result_df = result_df[['code'] + result_df.columns[:-1].tolist()]

这个方案的速度取决于词汇表大小,如果词汇量不是特别夸张(比如几万级),处理10k×3k的数据可能只需要几秒到几十秒,比原代码快几百倍都有可能。


方案3:多进程并行处理(超大数据量救星)

如果你的数据量还在往上走,比如10万行×5千行,那可以用多进程把任务拆分到多个CPU核心上,进一步压榨硬件性能。

import pandas as pd
import multiprocessing as mp

# 预转换集合
set_list1 = data['text_tokenized'].apply(set).tolist()
set_list2 = data2['text_tokenized'].apply(set).tolist()
codes = data['code'].tolist()

# 定义单个行的处理函数
def calculate_row_similarity(s1):
    return [len(s1 & s2) for s2 in set_list2]

# 用CPU全部核心创建进程池
with mp.Pool(mp.cpu_count()) as pool:
    similarity_matrix = pool.map(calculate_row_similarity, set_list1)

# 生成结果DataFrame
result_df = pd.DataFrame(
    similarity_matrix,
    columns=[f"df2_row_{idx}" for idx in range(len(set_list2))]
)
result_df['code'] = codes
result_df = result_df[['code'] + result_df.columns[:-1].tolist()]

这个方案的速度提升倍数大概等于你的CPU核心数(比如8核就能快8倍左右),适合处理超大规模的数据集。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 08:45:05