如何将DataFrame.iterrows()改写为列表推导/向量化以提升性能?
优化Pandas中计算SacreBLEU分数的性能(替代iterrows)
原代码问题
原代码使用df.iterrows()逐行循环,不仅性能低下(每次循环生成Series对象带来额外开销),而且逐行判断缺失值的方式不符合Pandas最佳实践。
优化方案1:列表推导+批量过滤缺失行
先通过Pandas内置的dropna批量过滤掉含缺失值的行,再用列表推导生成分数列表,性能比iterrows提升显著:
import pandas as pd from sacrebleu import corpus_bleu def calculate_score(references, hypothesis): return corpus_bleu([hypothesis], [references]).score # 读取数据 df = pd.read_excel("data.xlsx") # 批量过滤Data1/Data2/Data3存在缺失值的行 filtered_df = df.dropna(subset=["Data1", "Data2", "Data3"]) # 列表推导生成分数列表 scores = [calculate_score(ref, hyp) for ref, hyp in zip(filtered_df["Data1"], filtered_df["Data2"])] # 计算平均分 average_score = sum(scores) / len(scores) if scores else 0
优化方案2:批量调用SacreBLEU(性能最优)
SacreBLEU的corpus_bleu本身支持批量处理文本,直接传入整列的文本列表,完全避开Python循环,是数据量较大时的最优选择:
import pandas as pd from sacrebleu import corpus_bleu def calculate_batch_scores(references, hypotheses): # 批量计算每行的BLEU分数 return corpus_bleu(hypotheses, [references]).scores df = pd.read_excel("data.xlsx") filtered_df = df.dropna(subset=["Data1", "Data2", "Data3"]) # 传入整列的原生列表进行批量计算 scores = calculate_batch_scores(filtered_df["Data1"].tolist(), filtered_df["Data2"].tolist()) average_score = sum(scores) / len(scores) if scores else 0
优化逻辑说明
- 批量过滤缺失值:
dropna是Pandas底层实现的方法,基于C语言加速,比Python循环里逐行判断pd.isna快数倍。 - 避免iterrows开销:
iterrows每次迭代都会生成一个Series对象,带来大量不必要的内存和计算开销;列表推导直接操作原生序列,批量处理的方式则完全利用SacreBLEU的批量计算能力,性能提升最明显。
内容的提问来源于stack exchange,提问作者Raptor
相关产品推荐
相关产品推荐

