Polars中行迭代:不规则采样时间序列的指数加权和快速计算
Polars中原生实现依赖前序结果的指数累加计算
你需要实现的是依赖前一行计算结果的指数累加逻辑(exp_sum[i] = exp_sum[i-1] * decay[i] + signal[i]),这类带状态的迭代计算无法向量化,想知道Polars是否有原生高性能实现,以及背后的原因。
目前没有Polars原生的高性能实现方式
核心原因:列存储的天然限制
Polars底层采用列存储架构,官方文档明确提到:
由于底层数据采用列存储,行迭代并非最优方式;如有可能,优先使用专用导出/输出方法。
列存储的优势是对整列做批量运算,而这类需要逐行依赖前序状态的计算,需要频繁跨行访问数据,完全违背了列存储的优化方向,因此Polars没有针对这类场景设计原生的高性能API。
当前最优方案:Polars + Numba
你现在用Polars转Numpy数组再调用Numba函数的方案,就是当前的最优解。如果想减少格式转换的开销,可以直接用Polars的to_numpy()提取列数据,计算后再转回Polars列,示例代码如下:
import polars as pl import numba as nb import numpy as np @nb.jit(nopython=True) def exponential_sum(signal, decay, initial_value=0): n = len(signal) exp_sum = np.zeros(n) exp_sum[0] = signal[0] if initial_value == 0 else initial_value * decay[0] + signal[0] for i in range(1, n): exp_sum[i] = exp_sum[i-1] * decay[i] + signal[i] return exp_sum # 构造示例Polars DataFrame df = pl.DataFrame({ "times": [1.0, 2.0, 3.0, 4.0], "signal": [10, 20, 30, 40] }) alpha = -0.5 # 计算decay列,填充第一行的null值 df = df.with_columns( decay=pl.col("times").diff().exp() * alpha ).fill_null(1.0) # 提取数组并计算 signal_np = df["signal"].to_numpy() decay_np = df["decay"].to_numpy() exp_sum_np = exponential_sum(signal_np, decay_np) # 将结果转回Polars列 df = df.with_columns(exp_sum=pl.Series(exp_sum_np)) print(df)
关于未来是否会支持原生实现
Polars的核心定位是向量化列处理引擎,这类带状态的逐行迭代计算不属于它的核心优化场景。除非社区有大量迫切需求,否则官方大概率不会推出原生API——毕竟这类场景Numba已经能高效解决,Polars没必要在自己的短板方向投入资源。
内容的提问来源于stack exchange,提问作者Chris Russell
相关产品推荐
相关产品推荐

