Polars中遍历列执行转换的最优方法及推荐实现方式
Polars中遍历列执行转换的最优方法及推荐实现方式
首先,我理解你想要实现的是:用df1的每一列作为行权重,计算df2各列的加权平均值——也就是对df2每一列,按行乘以对应df1列的权重,求和后再除以该权重列的总和,最终得到一个以df2列名为行、df1列名为列的结果表。
在Polars里,我们完全不需要像Pandas那样用apply循环处理,因为Polars天生支持高效的矢量化操作,不仅代码更简洁,性能也会好很多(尤其是数据量较大时)。下面给你两种推荐的实现方式:
方法一:矩阵乘法(最简洁高效)
利用Polars的矩阵乘法特性,直接通过转置和乘法完成计算,完全规避循环:
import polars as pl import numpy as np # 生成示例数据 df1 = pl.DataFrame( { "A": np.random.rand(10), "B": np.random.rand(10), "C": np.random.rand(10) } ) df2 = pl.DataFrame( { "X1": np.random.rand(10), "X2": np.random.rand(10), "X3": np.random.rand(10) } ) # 计算权重列的总和 weights_sum = df1.sum() # 核心计算:转置df2后与df1做矩阵乘法,再除以权重总和 result = (df2.transpose() @ df1) / weights_sum print(result)
逻辑说明:
df2.transpose()把df2从10行3列转为3行10列,df1是10行3列,两者相乘后得到3行3列的结果(对应df2的列 ×df1的列)- 除以
weights_sum(df1各列的总和),就得到了每一组的加权平均值,最终结果的结构和你Pandas代码输出完全一致。
方法二:表达式生成(更灵活,适合复杂场景)
如果需要更定制化的操作,可以通过生成表达式的方式构建计算逻辑,同样不需要显式循环:
# 为df1的每一列生成对应的加权平均表达式 exprs = [ (pl.sum(df2.select(pl.all() * pl.col(weight_col))) / pl.sum(pl.col(weight_col))).alias(weight_col) for weight_col in df1.columns ] # 生成结果并转置成目标格式 result = pl.DataFrame(exprs).transpose( include_header=True, header_name="column", column_names=df1.columns ).rename({"column": ""}) print(result)
逻辑说明:
- 遍历
df1的列名,对每个权重列,计算df2所有列与该权重列的乘积之和,再除以权重列的总和 - 最后通过转置调整结果的行列结构,匹配需求的输出格式。
为什么不推荐循环?
Polars的核心优势在于矢量化计算,它的查询引擎会自动优化矢量化操作的执行效率。如果像Pandas那样用循环或apply逐列处理,会完全浪费Polars的性能优势,尤其是数据量较大时,矢量化实现的速度会比循环快一个数量级以上。
备注:内容来源于stack exchange,提问作者Sharma
相关产品推荐
相关产品推荐

