You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 03:01:21