如何用Struct将Polars DataFrame与偏移版合并为单表?
实现方法与效率分析
方案一:关联偏移表后打包Struct
先生成偏移2期的DataFrame,通过日期关联原表,再对目标列进行Struct封装:
import polars as pl # 构造示例股价数据 data = { "date": ["2024-01-01", "2024-01-02", "2024-01-03", "2024-01-04", "2024-01-05"], "ibm": [150.0, 152.0, 151.5, 153.0, 154.2], "apple": [190.5, 192.3, 191.8, 193.5, 194.1], "coinbase": [70.2, 71.5, 70.8, 72.0, 71.3], "other_col": [1, 2, 3, 4, 5] } df = pl.DataFrame(data).with_columns(pl.col("date").str.to_date()) # 生成偏移2个日期单位的表 df_2 = df.select("date", "ibm", "apple", "coinbase").shift(-2) # 关联原表与偏移表,将对应列打包为Struct target_cols = ["ibm", "apple", "coinbase"] result_df = df.join(df_2, on="date", suffix="_shifted").with_columns( [ pl.struct(current=pl.col(col), shifted_2=pl.col(f"{col}_shifted")).alias(col) for col in target_cols ] ).drop([f"{col}_shifted" for col in target_cols]) print(result_df)
方案二:直接用表达式链式操作(推荐)
不需要单独生成偏移表,直接在原表中通过shift(-2)获取偏移值并封装Struct,代码更简洁且效率更高:
import polars as pl # 构造示例数据(同方案一) data = { "date": ["2024-01-01", "2024-01-02", "2024-01-03", "2024-01-04", "2024-01-05"], "ibm": [150.0, 152.0, 151.5, 153.0, 154.2], "apple": [190.5, 192.3, 191.8, 193.5, 194.1], "coinbase": [70.2, 71.5, 70.8, 72.0, 71.3], "other_col": [1, 2, 3, 4, 5] } df = pl.DataFrame(data).with_columns(pl.col("date").str.to_date()) target_cols = ["ibm", "apple", "coinbase"] result_df = df.with_columns( [ pl.struct(current=pl.col(col), shifted_2=pl.col(col).shift(-2)).alias(col) for col in target_cols ] ) print(result_df)
效率对比
- 方案一:依赖
join操作对齐日期,会产生额外的内存开销(存储完整的偏移表),计算时间复杂度约为O(n log n),适合小规模数据或需要保留偏移表单独使用的场景。 - 方案二:利用Polars的列式计算优势,直接在原列上生成偏移值并封装Struct,属于原地操作,时间复杂度为O(n),内存占用仅为原表的极小增量(仅存储偏移后的列数据)。对于百万行以上的大规模数据集,方案二的效率优势会非常显著,同时代码更简洁易维护。
内容的提问来源于stack exchange,提问作者Des1303
相关产品推荐
相关产品推荐

