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

如何在Polars中实现按日期偏移(Shift by Date)获取前序日期值?

实现Polars按日期偏移(Shift by Date)获取前一个可用日期的k值

要实现按实际存在的前一个日期而非固定行数偏移来获取对应k值,核心思路是先统一每个日期的k值,再按日期排序后偏移,最后将结果广播回原数据的所有行。以下是两种简洁的实现方式:

方法一:使用临时映射表Join(直观易懂)

  1. 提取每个日期与对应k值的唯一映射关系(因同一日期的k值完全相同)
  2. 对映射表按日期排序,用shift(1)获取前一个日期的k值
  3. 将映射表关联回原DataFrame,完成列填充
import polars as pl
import numpy as np
import datetime

# 你的原始代码(保持不变)
np.random.seed(1)
df = (pl
  .DataFrame(dict(
    dt=np.random.randint(datetime.datetime(2023, 1, 1).timestamp(), datetime.datetime(2023, 1, 31).timestamp(), 100)
    ))
  .select(
    pl.from_epoch('dt').sort()
    )
  .filter(
    (pl.col('dt').dt.day().cos() * 17).floor() % 3 == 0
    )
  .pipe(lambda df: df.with_columns(
    j=pl.lit(np.random.randint(10, 99, df.height)),
    ))
  .with_columns(
    k=pl.col('j').last().over(pl.col('dt').dt.date()),
    )
  )

# 步骤1:生成日期-k的唯一映射表
date_k_map = df.select(
    pl.col('dt').dt.date().alias('date'),
    pl.col('k')
).unique()

# 步骤2:按日期排序并获取前一个日期的k值
date_k_map = date_k_map.sort('date').with_columns(
    prev_k=pl.col('k').shift(1)
)

# 步骤3:关联回原DataFrame,得到l列
df = df.join(
    date_k_map,
    left_on=pl.col('dt').dt.date(),
    right_on='date',
    how='left'
).drop('date').rename({'prev_k': 'l'})

print(df.head())

方法二:使用窗口函数链式调用(更简洁)

利用Polars的窗口函数特性,直接在原DataFrame中完成计算,无需额外生成映射表:

# 在你的原始df基础上添加l列
df = df.with_columns(
    l=pl.col('k')
        # 统一同一日期的k值(取第一个即可,因所有行k相同)
        .first().over(pl.col('dt').dt.date())
        # 按日期全局排序,保证偏移顺序正确
        .sort_by(pl.col('dt').dt.date())
        # 偏移一行,得到前一个日期的k值
        .shift(1)
        # 将偏移结果广播回同一日期的所有行
        .over(pl.col('dt').dt.date())
)

关键说明

  • 普通shift(1)仅按行偏移,若同一日期有多行,会错误取到同一日期内上一行的k值;而上述方法先统一每个日期的k值,再按日期维度排序偏移,确保取到的是前一个完整可用日期的k值。
  • 两种方法最终效果一致:第一个出现的日期的l列为null,后续每个日期的l列均为前一个存在日期的k值。

内容的提问来源于stack exchange,提问作者levant pied

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 11:27:45