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

如何加速Pandas DataFrame的字符串相似度计算?

优化字符串相似度计算的超实用方案

兄弟,6000条Yahoo数据×13万条PTT数据的双重循环跑7天,这效率确实让人崩溃!咱们从替换低效计算库、并行化处理、避免Pandas逐行赋值这几个核心方向入手,把速度提上去。

核心问题分析

你当前的代码慢有两个关键原因:

  1. difflib.SequenceMatcher是纯Python实现的相似度算法,计算单条就慢,乘以千万级别的计算量直接爆炸。
  2. 双重循环里用df_post.loc[j, ...]逐行赋值,Pandas的这种操作效率极低,相当于每次都要修改整个DataFrame的结构。

优化方案一:用C实现的Levenshtein库替换difflib

python-Levenshtein是基于C语言实现的字符串相似度计算库,比difflib快几十到上百倍,完全兼容你的需求(计算两个字符串的相似度比例)。

首先安装依赖:

pip install python-Levenshtein joblib

然后重构代码,用并行计算+数组操作替代双重循环:

import pandas as pd
import Levenshtein
from joblib import Parallel, delayed

# 1. 读取并预处理数据
df_post = pd.read_csv('ptt_run.csv', encoding='utf8', header=0).fillna('null')
df_yahoo = pd.read_csv('yahoo_movie_20180519_test.csv', encoding='utf8', header=0).fillna('null')

# 2. 提取核心列转为Numpy数组(比Pandas列访问快很多)
yahoo_texts = df_yahoo['yahoo_ch_nosign'].values
post_texts = df_post['title_nosign'].values
yahoo_ids = df_yahoo['yahoo_movie_id'].values

# 3. 定义单条Yahoo数据的相似度计算函数
def compute_sim(yahoo_text, yahoo_id):
    # 用Levenshtein.ratio计算相似度,比difflib快N倍
    sim_scores = [Levenshtein.ratio(yahoo_text, post_text) for post_text in post_texts]
    return (yahoo_id, sim_scores)

# 4. 并行计算:利用所有CPU核心同时处理Yahoo数据
# verbose=10可以看到实时进度
results = Parallel(n_jobs=-1, verbose=10)(
    delayed(compute_sim)(text, idx) for text, idx in zip(yahoo_texts, yahoo_ids)
)

# 5. 批量赋值到DataFrame(避免逐行修改)
for yahoo_id, scores in results:
    df_post[yahoo_id] = scores

# 6. 保存结果
df_post.to_csv('df_score_test.csv', encoding='utf8', index=False)

优化方案二:内存不足时的分块处理

如果你的机器内存不够(13万×6000的float64数据大概占6GB内存),可以把PTT数据分成小块处理,降低内存压力:

import pandas as pd
import Levenshtein
from joblib import Parallel, delayed

df_post = pd.read_csv('ptt_run.csv', encoding='utf8', header=0).fillna('null')
df_yahoo = pd.read_csv('yahoo_movie_20180519_test.csv', encoding='utf8', header=0).fillna('null')

yahoo_texts = df_yahoo['yahoo_ch_nosign'].values
post_texts = df_post['title_nosign'].values
yahoo_ids = df_yahoo['yahoo_movie_id'].values

# 把PTT数据分成10块(每块1.3万条),根据你的内存调整chunk_size
chunk_size = 13000
post_chunks = [post_texts[i:i+chunk_size] for i in range(0, len(post_texts), chunk_size)]

def compute_sim_chunk(yahoo_text, yahoo_id, post_chunk):
    sim_scores = [Levenshtein.ratio(yahoo_text, post_text) for post_text in post_chunk]
    return (yahoo_id, sim_scores)

# 逐块计算并赋值
for chunk_idx, post_chunk in enumerate(post_chunks):
    print(f"正在处理第 {chunk_idx+1}/{len(post_chunks)} 块数据")
    start_row = chunk_idx * chunk_size
    end_row = start_row + len(post_chunk)
    
    # 并行计算当前块的相似度
    chunk_results = Parallel(n_jobs=-1, verbose=5)(
        delayed(compute_sim_chunk)(text, idx, post_chunk) for text, idx in zip(yahoo_texts, yahoo_ids)
    )
    
    # 把结果赋值到对应行
    for yahoo_id, scores in chunk_results:
        df_post.loc[start_row:end_row-1, yahoo_id] = scores

df_post.to_csv('df_score_test.csv', encoding='utf8', index=False)

效果预估

  • 单条计算速度:Levenshtein比difflib快50-100倍。
  • 并行计算:如果你的机器有8核CPU,总时间可以降到原来的1/8左右。
  • 综合下来,原来7天的计算量,现在应该能在几小时内完成(甚至更快,取决于CPU核心数)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 06:56:07