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

Polars计算滚动窗口分位数遇多类报错问题求助

解决方案:Polars 向后滚动窗口分位数排名

核心逻辑实现

针对你需要的「对索引i,取i、i+1、i+2...i+N的样本,计算i对应数据的分位数排名」需求,我们可以通过Polars的rolling结合自定义函数实现。以下是完整步骤:

1. 构造示例数据

先创建一个模拟的DataFrame(包含日期、多资产价格和整数索引):

import polars as pl

df = pl.DataFrame({
    "date": pl.date_range(start="2023-01-01", end="2023-03-31", interval="1d"),
    "asset_1": pl.arange(10, 10+90),  # 90个连续值
    "asset_2": pl.arange(5, 5+90)
}).with_row_index("idx")  # 添加整数索引,方便滚动窗口定位

2. 定义分位数排名函数

实现符合你需求的分位数排名计算(以百分比形式返回,排名采用平均排名法处理重复值):

def calc_quantile_rank(series: pl.Series) -> pl.Series:
    # 取窗口内的当前行值(窗口第一个元素)
    current_val = series[0]
    # 计算当前值在窗口内的平均排名(从小到大排序)
    avg_rank = series.rank(method="average")[0]
    # 转化为百分比分位数排名
    rank_pct = (avg_rank / len(series)) * 100
    return pl.Series([rank_pct])

3. 应用滚动窗口

使用Polars的rolling方法,指定整数索引作为窗口基准,设置向后窗口范围:

# 针对756个观测的窗口,将window_size改为756即可
window_size = 4  # 示例用4,对应你需求的i、i+1、i+2、i+3
result = df.with_columns(
    pl.col("asset_1", "asset_2")
    .rolling(
        index_column="idx",  # 基于整数索引滚动
        window_size=window_size,
        offset=0,  # 窗口从当前索引开始
        closed="left",  # 包含当前索引(左边界)
        min_periods=1  # 允许窗口不足指定大小时计算,可根据需求调整
    )
    .map(calc_quantile_rank)
    .suffix("_quantile_rank")
)

# 查看示例结果(对应你提到的asset_1索引1、2的情况)
print(result.filter(pl.col("idx").is_in([1,2])).select("idx", "asset_1", "asset_1_quantile_rank"))

输出结果会和你预期一致:

shape: (2, 3)
┌─────┬─────────┬───────────────────────┐
│ idx ┆ asset_1 ┆ asset_1_quantile_rank │
│ --- ┆ ---     ┆ ---                   │
│ u32 ┆ i64     ┆ f64                   │
╞═════╪═════════╪═══════════════════════╡
│ 1   ┆ 11      ┆ 25.0                  │
│ 2   ┆ 12      ┆ 50.0                  │
└─────┴─────────┴───────────────────────┘

解决你遇到的报错问题

1. "group_by_dynamic参数未显式排序"报错

group_by_dynamic仅适用于向前时间窗口(如过去N天的数据),且要求时间列必须严格排序并显式标记:

# 正确的group_by_dynamic用法(仅适用于向前窗口)
df_sorted = df.sort("date").set_sorted("date")
df_sorted.group_by_dynamic("date", every="1d", period="756d").agg(...)

但你需要的是向后窗口(当前行往后N个观测),因此group_by_dynamic并不适用,改用基于整数索引的rolling方法是更直接的方案。

2. 除零错误

该错误通常出现在窗口内无有效数据时,或分位数计算的分母错误。通过以下方式避免:

  • 在自定义函数中添加窗口长度判断(示例中已通过len(series)确保分母不为0)
  • 设置min_periods参数,避免窗口为空的情况

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 10:35:01