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

Polars:如何规避「聚合中不允许窗口表达式」错误及原理解析

问题解答

1. 保留分步写法的错误修复方案

你的核心问题是把**分组聚合(group_by.agg)和窗口函数(.over())**的用法混在了一起,导致逻辑冲突。要保留分步链式的写法,直接在with_columns里给每个指标计算加上.over("company")即可,无需用group_by.agg——因为窗口函数本身就支持按指定字段分组逐行计算,完全符合你要的分步可读性:

import polars as pl

# 假设你的原始数据包含 company、date、close 字段
df = (
    df
    # 先按公司+日期排序,保证时间序列计算的正确性
    .sort(["company", "date"])
    .with_columns(
        # 按company分组计算收益率
        收益率=pl.col("close").pct_change().over("company"),
        # 按company分组计算涨跌额
        涨跌额=pl.col("close").diff().over("company"),
        # 按company分组计算5日移动平均
        移动平均=pl.col("close").rolling_mean(window_size=5).over("company"),
        # 按company分组计算14日RSI
        RSI=pl.col("close").rsi(window_size=14).over("company")
    )
)

如果你的需求是每个公司只返回一行聚合结果(而非逐行保留原始数据),那就要放弃窗口函数,改用group_by.agg,但此时要使用聚合逻辑的函数(比如取最后值、均值等),而不是窗口类的计算:

df_agg = (
    df
    .sort(["company", "date"])
    .group_by("company")
    .agg(
        最新收益率=pl.col("close").pct_change().last(),
        最新移动平均=pl.col("close").rolling_mean(window_size=5).last(),
        最新RSI=pl.col("close").rsi(window_size=14).last()
    )
)

2. 为什么聚合操作里不能用窗口表达式?

用通俗的话讲,这俩是完全相反的操作逻辑:

  • 聚合操作(group_by.agg)是「把一个分组里的多行数据“压缩”成一行结果」——比如把一个公司的所有交易日数据,变成一行该公司的汇总指标。
  • 窗口函数(.over())是「给每一行数据“附加”一个基于其所在分组的计算结果」——比如给每个交易日的数据,加上该公司的5日均线,最终行数和原始数据一样多。

如果在聚合里用窗口表达式,就相当于你一边要把一个班级的所有学生成绩“压缩”成一行班级平均分,一边又要给每个学生都算一遍班级平均分并保留所有行,这俩需求是矛盾的。Polars无法理解你到底要“缩成一行”还是“保留所有行”,所以直接报错禁止这种混用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 11:26:25