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

如何在Polars中按ID和45分钟时间阈值分组生成新列?

在Polars中按分组生成45分钟时间间隔标记列

需求说明

现有包含col1(分组键)和col2(已转换为datetime类型)的Polars DataFrame,需要按col1分组,将每组内的col2按45分钟时间区间划分,生成col3列——同一45分钟区间内的记录col3值相同,后续区间值依次递增。

示例数据

import polars as pl

data = {
    "col1": [1, 1, 1,1,1,1,1,1,1,1,1,1, 2, 2,2,2,2,2,2,2,2,2,2],
    "col2": [
        "2022-05-25T08:00:00.648681",
        "2022-05-25T08:15:00.648681",
        "2022-05-25T08:30:00.648681",
        "2022-05-25T08:45:00.648681",
        "2022-05-25T09:00:00.648681",
        "2022-05-25T09:15:00.648681",
        "2022-05-25T09:30:00.648681",
        "2022-05-25T09:45:00.648681",
        "2022-05-25T10:00:00.648681",
        "2022-05-25T10:15:00.648681",
        "2022-05-25T10:30:00.648681",
        "2022-05-25T10:45:00.648681",
        "2022-05-25T08:00:00.648681",
        "2022-05-25T08:15:00.648681",
        "2022-05-25T08:30:00.648681",
        "2022-05-25T08:45:00.648681",
        "2022-05-25T09:00:00.648681",
        "2022-05-25T06:00:00.648681",
        "2022-05-25T06:15:00.648681",
        "2022-05-25T06:30:00.648681",
        "2022-05-25T06:45:00.648681",
        "2022-05-25T07:00:00.648681",
        "2022-05-25T07:15:00.648681",
    ],
}

df = pl.DataFrame(data)
df = df.with_columns(pl.col("col2").str.to_datetime())

期望输出

┌──────┬────────────────────────────┬──────┐
│ col1 ┆ col2                       ┆ col3 │
│ ---  ┆ ---                        ┆ ---  │
│ i64  ┆ datetime[μs]               ┆ u32  │
╞══════╪════════════════════════════╪══════╡
│ 1    ┆ 2022-05-25 08:00:00.648681 ┆ 1    │
│ 1    ┆ 2022-05-25 08:15:00.648681 ┆ 1    │
│ 1    ┆ 2022-05-25 08:30:00.648681 ┆ 1    │
│ 1    ┆ 2022-05-25 08:45:00.648681 ┆ 1    │
│ 1    ┆ 2022-05-25 09:00:00.648681 ┆ 2    │
│ 1    ┆ 2022-05-25 09:15:00.648681 ┆ 2    │
│ 1    ┆ 2022-05-25 09:30:00.648681 ┆ 2    │
│ 1    ┆ 2022-05-25 09:45:00.648681 ┆ 2    │
│ 1    ┆ 2022-05-25 10:00:00.648681 ┆ 3    │
│ 1    ┆ 2022-05-25 10:15:00.648681 ┆ 3    │
│ 1    ┆ 2022-05-25 10:30:00.648681 ┆ 3    │
│ 1    ┆ 2022-05-25 10:45:00.648681 ┆ 3    │
│ 2    ┆ 2022-05-25 08:00:00.648681 ┆ 3    │
│ 2    ┆ 2022-05-25 08:15:00.648681 ┆ 3    │
│ 2    ┆ 2022-05-25 08:30:00.648681 ┆ 3    │
│ 2    ┆ 2022-05-25 08:45:00.648681 ┆ 3    │
│ 2    ┆ 2022-05-25 09:00:00.648681 ┆ 4    │
│ 2    ┆ 2022-05-25 06:00:00.648681 ┆ 1    │
│ 2    ┆ 2022-05-25 06:15:00.648681 ┆ 1    │
│ 2    ┆ 2022-05-25 06:30:00.648681 ┆ 1    │
│ 2    ┆ 2022-05-25 06:45:00.648681 ┆ 1    │
│ 2    ┆ 2022-05-25 07:00:00.648681 ┆ 2    │
│ 2    ┆ 2022-05-25 07:15:00.648681 ┆ 2    │
└──────┴────────────────────────────┴──────┘

解决方案

方法一:时间向下取整+稠密排名

通过将时间戳向下取整到45分钟区间,再对分组内的取整结果做稠密排名,实现区间标记:

result_df = df.group_by("col1", maintain_order=True).agg(
    pl.col("col2"),
    col3=pl.col("col2")
        .dt.floor("45m")  # 将时间向下取整到最近的45分钟起始点
        .rank(method="dense", order="asc")  # 对取整结果做稠密排名,同一区间排名相同
).explode(["col2", "col3"])  # 将聚合后的列表展开回原行结构

print(result_df)

方法二:计算时间差+区间编号

通过计算每个时间点与分组内最早时间的差值,转换为分钟数后整除45,得到区间编号:

result_df = df.group_by("col1", maintain_order=True).agg(
    pl.col("col2"),
    col3=(pl.col("col2") - pl.col("col2").min())  # 计算与分组内最早时间的差值
        .dt.total_minutes()  # 转换为总分钟数
        .floordiv(45) + 1  # 整除45得到区间索引(从0开始),加1让编号从1开始
).explode(["col2", "col3"])

print(result_df)

两种方法都能生成符合要求的col3列,可根据习惯选择。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 04:44:58