优化pandas双层for循环 提升列间差值平方和计算效率
性能瓶颈原因
你当前的实现慢是必然的,核心问题有三个:
- 800*800共64万次Python层双层循环,每次循环都要做对象寻址、类型校验,完全没用到pandas/NumPy底层的C级向量化优化
- 循环内反复调用
.loc逐单元格赋值,pandas的单元素索引操作开销极高 - 简单的两列相减特意调用
.eval执行,额外增加了表达式解析的成本
你提到的.cov()之所以几秒就能跑完,本质是它底层直接走优化过的BLAS矩阵运算,全程没有Python层面的循环开销。
最优实现方案
你要算的列对逐行差平方和,完全可以通过代数变形转化为矩阵运算,不需要写任何循环,运行时间可以从几小时压缩到毫秒级。
首先做公式变形:对任意两列x、y,逐行差平方和满足sum((x_i - y_i)^2) = sum(x_i²) - 2*sum(x_i*y_i) + sum(y_i²)
基于这个公式的实现代码如下:
import pandas as pd import numpy as np # 计算每列的平方和,形状为(800,) col_square_sum = (year1_normalized_p ** 2).sum(axis=0).to_numpy() # 计算列间内积矩阵,形状为(800, 800),对应所有列对的乘积和 cross_product = year1_normalized_p.to_numpy().T @ year1_normalized_p.to_numpy() # 利用NumPy广播机制生成最终结果矩阵 sqdiff_result = col_square_sum.reshape(-1, 1) - 2 * cross_product + col_square_sum.reshape(1, -1) # 转换为对齐原索引列名的DataFrame sqdiff_df = pd.DataFrame( sqdiff_result, index=year1_normalized_p.columns, columns=year1_normalized_p.columns )
这个计算结果和你双层循环的输出完全等价,因为是严格的数学恒等变形,没有精度损失。
如果你不想手动推导公式,也可以直接调用距离计算函数,欧氏距离的平方正好就是你需要的逐行差平方和:
from sklearn.metrics.pairwise import euclidean_distances # 计算列之间的平方欧氏距离,注意要把原表转置,把列转为距离计算的样本 sqdiff_result = euclidean_distances(year1_normalized_p.T, squared=True) sqdiff_df = pd.DataFrame( sqdiff_result, index=year1_normalized_p.columns, columns=year1_normalized_p.columns )
注意事项
- 如果你的数据表中存在缺失值,需要提前用
dropna()或者fillna()处理,否则矩阵运算会传播空值 - 不要用逐行、逐单元格的操作写pandas代码,所有涉及全表批量计算的逻辑,优先找向量化实现,性能差距会是成百上千倍的
内容的提问来源于stack exchange,提问作者jsacor
相关产品推荐
相关产品推荐

