如何优化双字词PMI统计函数以提升百万级数据集的运行效率?
如何优化双字词PMI统计函数以提升百万级数据集的运行效率?
兄弟我太懂你这种百万级数据卡到怀疑人生的感受了!嵌套循环在大数据面前完全是效率杀手,咱们直接拆解问题、搞优化,保证速度能提N个档次~
先说说原代码的核心问题
你原来的嵌套for循环是**O(n*m)**的时间复杂度——每一个PMI短语都要遍历一遍整个freq_list找匹配,百万级数据下相当于要做10^12次操作?这能不慢吗!而且循环里逐个往列表里append数据,最后再转DataFrame,这也是隐形的耗时点。
直接上优化方案,一步到位
核心思路就是用字典实现O(1)快速查找+批量操作代替循环,优化后的代码如下:
def pmi_count_phrase_create(pmi_tups, freq_list): import pandas as pd """ pmi_tups是finder.score_ngrams(bigram_measures.pmi)的结果,格式为[((phrase), pmi), ...] freq_list是finder.ngram_fd.items()的结果,格式为[((phrase), count), ...] -> 返回包含bigram-phrase、count、PMI score三列的DataFrame """ # 把freq_list转成字典,把查找速度从O(m)拉到O(1) freq_dict = dict(freq_list) # 批量拆分pmi_tups里的短语和PMI值,比循环逐个提取快N倍 phrases, pmis = zip(*pmi_tups) # 用字典映射快速获取每个短语的计数,找不到的话默认设为0(你也可以改成NaN) counts = [freq_dict.get(phrase, 0) for phrase in phrases] # 直接批量构造DataFrame,避免循环append列表的额外开销 result_df = pd.DataFrame({ 'bigram-phrase': phrases, 'count': counts, 'PMI score': pmis }) return result_df
为啥这代码快?给你掰扯清楚:
- 字典查找秒杀循环遍历:把freq_list转成字典后,找任意短语的计数都是瞬间完成的,时间复杂度直接从原来的O(n*m)降到O(n+m),百万级数据下这差距简直是天壤之别
- 批量拆分代替循环提取:
zip(*pmi_tups)是Python的原生批量操作,比你循环逐个取phrase和pmi高效太多 - 一次性构造DataFrame:原代码里循环append三个列表,最后还要转DataFrame,相当于多做了三次遍历;现在直接用批量数据构造,一步到位省掉很多额外操作
额外的进阶优化建议(如果数据量超大到内存都扛不住)
- 分批次处理:把pmi_tups分成若干小批次,每批次处理完合并DataFrame,避免一次性占满内存
- 用numpy加速:把phrases、pmis、counts转成numpy数组后再构造DataFrame,速度还能再提一档
- 提前清理数据:如果freq_list里有重复的短语,先去重再转字典,避免不必要的内存占用
备注:内容来源于stack exchange,提问作者98fly
相关产品推荐
相关产品推荐

