如何将Polars DataFrame各列除以另一DataFrame的对应列标量
Polars中按列对应标量完成逐元素除法的最优实现
我是Polars新手,现在需要处理一个场景:有一个m×n的Polars DataFrame(df),还有一个1×n的Polars DataFrame(scalars),要求把df的每一列,对应除以scalars中同列的那个标量值。
示例数据代码
import numpy as np import polars as pl cols = list('abc') df = pl.DataFrame(np.linspace(1, 9, 9).reshape(3, 3), schema=cols) scalars = pl.DataFrame(np.linspace(1, 3, 3)[:, None], schema=cols)
df的输出
shape: (3, 3) ┌─────┬─────┬─────┐ │ a ┆ b ┆ c │ │ --- ┆ --- ┆ --- │ │ f64 ┆ f64 ┆ f64 │ ╞═════╪═════╪═════╡ │ 1.0 ┆ 2.0 ┆ 3.0 │ │ 4.0 ┆ 5.0 ┆ 6.0 │ │ 7.0 ┆ 8.0 ┆ 9.0 │ └─────┴─────┴─────┘
scalars的输出
shape: (1, 3) ┌─────┬─────┬─────┐ │ a ┆ b ┆ c │ │ --- ┆ --- ┆ --- │ │ f64 ┆ f64 ┆ f64 │ ╞═════╪═════╪═════╡ │ 1.0 ┆ 2.0 ┆ 3.0 │ └─────┴─────┴─────┘
已有实现方式
Pandas+NumPy广播实现
我用Pandas结合NumPy广播可以轻松实现需求:
df.to_pandas() / scalars.to_numpy()
输出:
a b c 0 1.0 1.0 1.0 1 4.0 2.5 2.0 2 7.0 4.0 3.0
自行想到的Polars合并运算
我尝试通过合并两个DataFrame后运算:
(pl.concat([df, scalars]) .with_columns(pl.all() / pl.all().tail(1)) .head(-1))
输出:
shape: (3, 3) ┌─────┬─────┬─────┐ │ a ┆ b ┆ c │ │ --- ┆ --- ┆ --- │ │ f64 ┆ f64 ┆ f64 │ ╞═════╪═════╪═════╡ │ 1.0 ┆ 1.0 ┆ 1.0 │ │ 4.0 ┆ 2.5 ┆ 2.0 │ │ 7.0 ┆ 4.0 ┆ 3.0 │ └─────┴─────┴─────┘
Polars原生最优实现方法
方法1:利用Polars自动广播特性直接运算
Polars支持维度兼容的自动广播,scalars是1行n列,df是m行n列,直接做除法即可,Polars会自动把scalars的行广播到df的所有行:
result = df / scalars
输出和预期完全一致,代码简洁且性能最优。
方法2:提取标量值逐列运算
如果需要更明确地控制列对应关系,可以提取scalars中每列的单个值,对df的对应列做除法:
result = df.select([ pl.col(col) / scalars[col].item() for col in df.columns ])
这种方式逻辑直观,适合需要单独处理部分列的场景,性能与广播方法接近。
方法3:显式广播后运算
可以把scalars显式广播到和df相同的行数,再做除法,适合需要明确广播步骤的场景:
result = df / scalars.with_row_count().drop("row_nr").broadcast_to(df.shape)
内容的提问来源于stack exchange,提问作者HavelTheGreat
相关产品推荐
相关产品推荐

