我有一个包含3列的Polars数据帧-组、日期、值.目标是 for each group的每个扩展窗口计算在每年的第一时间点结束的cumsum(value).

例如,对于以下示例数据帧:

import polars as pl

df = pl.DataFrame(
    {
        "date": [
            "2020-03-01",
            "2020-05-01",
            "2020-11-01",
            "2021-01-01",
            "2021-02-03",
            "2021-06-08",
            "2022-01-05",
            "2020-07-01",
            "2020-09-01",
            "2022-01-05",
            "2023-02-04",
        ],
        "group": [1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2],
        "value": [1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4],
    },
).with_columns(pl.col("date").str.strptime(pl.Date))

我想要的结果是:

┌────────────┬───────┬───────┐
│ date       ┆ group ┆ value │
│ ---        ┆ ---   ┆ ---   │
│ date       ┆ i64   ┆ i64   │
╞════════════╪═══════╪═══════╡
│ 2020-03-01 ┆ 1     ┆ 1     │
│ 2021-01-01 ┆ 1     ┆ 10    │
│ 2022-01-05 ┆ 1     ┆ 28    │
│ 2020-07-01 ┆ 2     ┆ 1     │
│ 2022-01-05 ┆ 2     ┆ 6     │
│ 2023-02-04 ┆ 2     ┆ 10    │
└────────────┴───────┴───────┘

基本上,在每年的第一天,分别为每一组计算从开始到(包括)这个特定日期的累计和value.

我试了group_by_dynamicrolling,但仍然找不到一个简洁明确的方法来解决这个问题.

任何 idea 都是受欢迎的.谢谢!

推荐答案

这似乎只是每组的常规累积总和:

df.with_columns(
   cum_sum = pl.col("value").cum_sum().over("group")
)
shape: (11, 4)
┌────────────┬───────┬───────┬─────────┐
│ date       ┆ group ┆ value ┆ cum_sum │
│ ---        ┆ ---   ┆ ---   ┆ ---     │
│ date       ┆ i64   ┆ i64   ┆ i64     │
╞════════════╪═══════╪═══════╪═════════╡
│ 2020-03-01 ┆ 1     ┆ 1     ┆ 1       │
│ 2020-05-01 ┆ 1     ┆ 2     ┆ 3       │
│ 2020-11-01 ┆ 1     ┆ 3     ┆ 6       │
│ 2021-01-01 ┆ 1     ┆ 4     ┆ 10      │
│ 2021-02-03 ┆ 1     ┆ 5     ┆ 15      │
│ 2021-06-08 ┆ 1     ┆ 6     ┆ 21      │
│ 2022-01-05 ┆ 1     ┆ 7     ┆ 28      │
│ 2020-07-01 ┆ 2     ┆ 1     ┆ 1       │
│ 2020-09-01 ┆ 2     ┆ 2     ┆ 3       │
│ 2022-01-05 ┆ 2     ┆ 3     ┆ 6       │
│ 2023-02-04 ┆ 2     ┆ 4     ┆ 10      │
└────────────┴───────┴───────┴─────────┘

然后保留每一年的第一行(按组):

df.with_columns(
   cum_sum = pl.col("value").cum_sum().over("group")
).filter(
   pl.col("date").dt.year().is_first_distinct().over("group")
)
shape: (6, 4)
┌────────────┬───────┬───────┬─────────┐
│ date       ┆ group ┆ value ┆ cum_sum │
│ ---        ┆ ---   ┆ ---   ┆ ---     │
│ date       ┆ i64   ┆ i64   ┆ i64     │
╞════════════╪═══════╪═══════╪═════════╡
│ 2020-03-01 ┆ 1     ┆ 1     ┆ 1       │
│ 2021-01-01 ┆ 1     ┆ 4     ┆ 10      │
│ 2022-01-05 ┆ 1     ┆ 7     ┆ 28      │
│ 2020-07-01 ┆ 2     ┆ 1     ┆ 1       │
│ 2022-01-05 ┆ 2     ┆ 3     ┆ 6       │
│ 2023-02-04 ┆ 2     ┆ 4     ┆ 10      │
└────────────┴───────┴───────┴─────────┘

一种更"直接"的方法可能是首先获取年度总和,然后从中生成CUM_SUM.

(df.group_by(
      "group", 
      pl.col("date").dt.year().alias("year"),
      maintain_order=True
   )
   .agg(
      pl.col("date").first(),
      pl.col("value").first(), 
      pl.col("value").sum().alias("sum"),
   )
   .with_columns(
      pl.when(pl.col("group").is_first_distinct())
        .then(pl.col("value"))
        .otherwise(
           pl.col("value") + pl.col("sum").cum_sum().shift().over("group")
        )
        .alias("cum_sum")
   )
)
shape: (6, 6)
┌───────┬──────┬────────────┬───────┬─────┬─────────┐
│ group ┆ year ┆ date       ┆ value ┆ sum ┆ cum_sum │
│ ---   ┆ ---  ┆ ---        ┆ ---   ┆ --- ┆ ---     │
│ i64   ┆ i32  ┆ date       ┆ i64   ┆ i64 ┆ i64     │
╞═══════╪══════╪════════════╪═══════╪═════╪═════════╡
│ 1     ┆ 2020 ┆ 2020-03-01 ┆ 1     ┆ 6   ┆ 1       │
│ 1     ┆ 2021 ┆ 2021-01-01 ┆ 4     ┆ 15  ┆ 10      │
│ 1     ┆ 2022 ┆ 2022-01-05 ┆ 7     ┆ 7   ┆ 28      │
│ 2     ┆ 2020 ┆ 2020-07-01 ┆ 1     ┆ 3   ┆ 1       │
│ 2     ┆ 2022 ┆ 2022-01-05 ┆ 3     ┆ 3   ┆ 6       │
│ 2     ┆ 2023 ┆ 2023-02-04 ┆ 4     ┆ 4   ┆ 10      │
└───────┴──────┴────────────┴───────┴─────┴─────────┘

Python相关问答推荐

如何根据日期和时间将状态更新为已过期或活动?

Polars比较了两个预设-有没有方法在第一次不匹配时立即失败

Pandas 有条件轮班操作

. str.替换pandas.series的方法未按预期工作

Pandas 都是(),但有一个门槛

通过pandas向每个非空单元格添加子字符串

我如何使法国在 map 中完全透明的代码?

Python中绕y轴曲线的旋转

如何在UserSerializer中添加显式字段?

转换为浮点,pandas字符串列,混合千和十进制分隔符

多指标不同顺序串联大Pandas 模型

如何在FastAPI中为我上传的json文件提供索引ID?

启动带有参数的Python NTFS会导致文件路径混乱

使用Python从rotowire中抓取MLB每日阵容

BeautifulSoup:超过24个字符(从a到z)的迭代失败:降低了首次深入了解数据集的复杂性:

按条件添加小计列

如何用FFT确定频变幅值

Python如何导入类的实例

递归链表反转与打印语句挂起

Pandas:根据相邻行之间的差异过滤数据帧