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

Polars中如何用group_by_dynamic忽略日期仅按时间分组?

问题描述

测试数据存储在mwe.csv中,格式如下:

datetime,duration_in_traffic_s
2023-12-20T10:50:43.063641000,221.0
2023-12-20T10:59:09.884939000,219.0
...(更多不同日期的行)

需求是使用Polars的group_by_dynamic函数,以每10分钟为间隔、1小时为窗口计算duration_in_traffic_s的平均值,且忽略日期,仅按一天中的时间分组(即2023-12-20 10:40和2023-12-21 10:40需归为同一组)。

当前执行的代码如下:

(
    pl.read_csv("mwe.csv")
    .with_columns(pl.col("datetime").cast(pl.Datetime))
    .sort("datetime")
    .group_by_dynamic(
        index_column="datetime",
        every="10m",
        period="1h",
    )
    .agg(pl.col("duration_in_traffic_s").mean())
)

但该代码会将不同日期的同一时间分为不同组,无法满足需求。尝试转换为时间类型或浮点数值的方式均无法适配group_by_dynamic的使用,且希望保留时间格式。

解决方案

核心思路是将所有datetime的日期部分统一替换为固定日期(比如2000-01-01),这样所有时间都落在同一天内,再使用group_by_dynamic即可实现按一天内的时间分组,最后提取结果中的时间部分即可。

完整代码实现:

import polars as pl

(
    pl.read_csv("mwe.csv")
    .with_columns(pl.col("datetime").cast(pl.Datetime))
    # 将所有datetime的日期替换为固定值,仅保留时间部分
    .with_columns(
        fixed_day_dt=pl.col("datetime").dt.replace(year=2000, month=1, day=1)
    )
    .sort("fixed_day_dt")
    .group_by_dynamic(
        index_column="fixed_day_dt",
        every="10m",
        period="1h",
        # 可选:设置窗口对齐方式,比如按整点对齐
        offset="0m"
    )
    .agg(pl.col("duration_in_traffic_s").mean().alias("avg_duration_s"))
    # 将结果中的datetime转换为时间格式,仅保留时分秒
    .with_columns(
        time_window=pl.col("fixed_day_dt").dt.time()
    )
    # 移除临时列,保留需要的结果列
    .drop("fixed_day_dt")
)

代码说明

  1. 统一日期部分:使用dt.replace()将所有datetime的日期替换为固定值(如2000-01-01),这样所有数据的时间维度都集中在同一天,group_by_dynamic会基于这一天的时间进行分组。
  2. 动态分组计算:基于处理后的fixed_day_dt执行group_by_dynamic,设置every="10m"(分组间隔)和period="1h"(窗口长度),计算窗口内的平均值。
  3. 保留时间格式:最后将结果中的fixed_day_dt转换为time类型,得到仅包含时分秒的窗口时间标识,同时移除临时列。

这样处理后,不同日期的同一时间段数据会被合并到同一个窗口中计算平均值,且结果保留了时间格式。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 18:05:53