iterrows的向量化替代方案:推文语义分析场景的代码提速问题
关于Numpy Vectorization优化推文语义分析代码的解答
核心误区澄清
numpy.vectorize 是语法糖,并不会真正执行C层面的并行向量化运算,它的内部实现依然是遍历每个输入元素逐次调用封装的Python函数,甚至因为额外的封装开销,运行速度会比你当前直接写的循环还要慢,不推荐用这种方式优化。
现有代码性能瓶颈
你当前代码的性能损耗主要来自两处:
- 用
iteritems遍历Pandas Series,本身遍历效率偏低 - 每次循环都调用
.loc对DataFrame做原位赋值,单次.loc索引的开销很高,数据量过万时累加开销会非常明显
优化方案
轻量优化(改动最小,性能提升10~50倍)
核心思路是先批量计算所有文本的情感结果,统一存储到列表后再一次性写入DataFrame,避免逐次调用.loc的开销:
import pandas as pd from nltk.sentiment import SentimentIntensityAnalyzer ss = SentimentIntensityAnalyzer() # 取出所有文本批量计算 texts = tw_list["full_text"].tolist() results = [] for text in texts: score = ss.polarity_scores(text) neg, neu, pos, comp = score["neg"], score["neu"], score["pos"], score["compound"] if neg > pos: res = ("negative", None, None, None, None) elif pos > neg: res = ("positive", None, None, None, None) else: res = ("neutral", neg, neu, pos, comp) results.append(res) # 一次性写入结果到DataFrame tw_list[["sentiment", "neg", "neu", "pos", "compound"]] = pd.DataFrame(results, index=tw_list.index)
如果你的业务需要所有行都存储情感分,只需要修改返回逻辑,每次都返回四个分数值即可。
大数量级进阶优化(并行处理)
如果你的数据量超过10万条,可以用多进程并行处理进一步提速,速度提升幅度和你的CPU核心数正相关:
import pandas as pd from nltk.sentiment import SentimentIntensityAnalyzer from multiprocessing import Pool, cpu_count ss = SentimentIntensityAnalyzer() def process_text(text): score = ss.polarity_scores(text) neg, neu, pos, comp = score["neg"], score["neu"], score["pos"], score["compound"] if neg > pos: return ("negative", None, None, None, None) elif pos > neg: return ("positive", None, None, None, None) else: return ("neutral", neg, neu, pos, comp) if __name__ == "__main__": # 调用CPU核心数-1的进程做并行计算 with Pool(cpu_count()-1) as p: results = p.map(process_text, tw_list["full_text"].tolist()) # 一次性写入结果 tw_list[["sentiment", "neg", "neu", "pos", "compound"]] = pd.DataFrame(results, index=tw_list.index)
内容的提问来源于stack exchange,提问作者Lukas Schmidt
相关产品推荐
相关产品推荐

