如何在Polars LazyFrame的同一语句中创建关联的两列?
Polars LazyFrame 同时生成两列的解决方案
背景与需求
从FRED API获取的Polars LazyFrame数据如下:
self.yielddiff_lf shape: (9, 5) ┌────────────┬────────────────────────────┬──────────┬──────────┬─────────────┐ │ statistic ┆ Date ┆ 5y Rate ┆ 1y Rate ┆ Rate Spread │ │ --- ┆ --- ┆ --- ┆ --- ┆ --- │ │ str ┆ str ┆ f64 ┆ f64 ┆ f64 │ ╞════════════╪════════════════════════════╪══════════╪══════════╪═════════════╡ │ count ┆ 82 ┆ 82.0 ┆ 82.0 ┆ 82.0 │ │ mean ┆ 2023-03-02 08:29:16.097000 ┆ 3.737073 ┆ 4.740244 ┆ -1.003171 │ │ std ┆ null ┆ 0.267561 ┆ 0.220112 ┆ 0.145185 │ │ min ┆ 2023-01-03 ┆ 3.36 ┆ 4.19 ┆ -1.29 │ │ 25% ┆ 2023-02-01 ┆ 3.54 ┆ 4.64 ┆ -1.12 │ │ 50% ┆ 2023-03-03 ┆ 3.66 ┆ 4.71 ┆ -1.03 │ │ 75% ┆ 2023-03-31 ┆ 3.93 ┆ 4.88 ┆ -0.92 │ │ max ┆ 2023-04-28 ┆ 4.34 ┆ 5.25 ┆ -0.6 │ └────────────┴────────────────────────────┴──────────┴──────────┴─────────────┘
需要完成两个计算:
- 创建
Rate Spread列:{numerator} Rate减去{denominator} Rate,结果保留3位小数 - 创建
Spread % Change列:基于Rate Spread列计算百分比变化后乘以100
错误尝试分析
尝试1:列未找到报错
self.yielddiff_lf = self.yielddiff_lf.with_columns( ( (pl.col(f"{numerator} Rate") - pl.col(f"{denominator} Rate")) .round(3).alias("Rate Spread") ), ( pl.col("Rate Spread").pct_change().alias("Spread % Change")*100 ) )
报错原因:同一with_columns调用中,新定义的Rate Spread列还未被添加到DataFrame,后续表达式无法直接引用。
尝试2:仅生成目标列丢失中间列
self.yielddiff_lf = self.yielddiff_lf.with_columns( ( (pl.col(f"{numerator} Rate") - pl.col(f"{denominator} Rate")) .round(3).alias("Rate Spread") ).pct_change().alias("Spread % Change")*100 )
问题:仅对Rate Spread的计算结果执行了pct_change,最终只输出Spread % Change列,未保留Rate Spread列。
可行解决方案
方法1:使用let表达式(Polars 0.19+推荐)
通过let定义临时变量,可在同一with_columns中复用计算逻辑:
self.yielddiff_lf = self.yielddiff_lf.with_columns( pl.let( rate_spread = (pl.col(f"{numerator} Rate") - pl.col(f"{denominator} Rate")).round(3), spread_pct_change = rate_spread.pct_change() * 100 ).alias("Rate Spread", "Spread % Change") )
方法2:链式调用with_columns
先创建Rate Spread列,再基于该列生成Spread % Change:
self.yielddiff_lf = self.yielddiff_lf.with_columns( (pl.col(f"{numerator} Rate") - pl.col(f"{denominator} Rate")) .round(3).alias("Rate Spread") ).with_columns( pl.col("Rate Spread").pct_change() * 100 .alias("Spread % Change") )
方法3:重复计算逻辑(不推荐,冗余)
如果不想用链式调用或let,可重复Rate Spread的计算逻辑:
self.yielddiff_lf = self.yielddiff_lf.with_columns( (pl.col(f"{numerator} Rate") - pl.col(f"{denominator} Rate")) .round(3).alias("Rate Spread"), ((pl.col(f"{numerator} Rate") - pl.col(f"{denominator} Rate")).round(3)) .pct_change() * 100 .alias("Spread % Change") )
内容的提问来源于stack exchange,提问作者WaqarQureshii
相关产品推荐
相关产品推荐

