时间序列

import polars as pl from datetime import datetime # 创建一个数据帧实例 df = pl.DataFrame( { "time": pl.date_range( low=datetime(2021, 12, 16), high=datetime(2021, 12, 16, 3), interval="30m", ), "n": range(7), } ) df
shape: (7, 2) ┌─────────────────────┬─────┐ │ time ┆ n │ │ --- ┆ --- │ │ datetime ┆ i64 │ ╞═════════════════════╪═════╡ │ 2021-12-16 00:00:00 ┆ 0 │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┤ │ 2021-12-16 00:30:00 ┆ 1 │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┤ │ 2021-12-16 01:00:00 ┆ 2 │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┤ │ 2021-12-16 01:30:00 ┆ 3 │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┤ │ 2021-12-16 02:00:00 ┆ 4 │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┤ │ 2021-12-16 02:30:00 ┆ 5 │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┤ │ 2021-12-16 03:00:00 ┆ 6 │ └─────────────────────┴─────┘

从2021-12-16 00:00:00开始,按1小时的窗口分组。

( df.groupby_dynamic("time", every="1h").agg( [pl.col("time").min(), pl.col("time").max()] ) )
shape: (3, 3) ┌─────────────────────┬─────────────────────┬─────────────────────┐ │ time ┆ time_min ┆ time_max │ │ --- ┆ --- ┆ --- │ │ datetime ┆ datetime ┆ datetime │ ╞═════════════════════╪═════════════════════╪═════════════════════╡ │ 2021-12-16 00:00:00 ┆ 2021-12-16 00:30:00 ┆ 2021-12-16 01:00:00 │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ 2021-12-16 01:00:00 ┆ 2021-12-16 01:30:00 ┆ 2021-12-16 02:00:00 │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ 2021-12-16 02:00:00 ┆ 2021-12-16 02:30:00 ┆ 2021-12-16 03:00:00 │ └─────────────────────┴─────────────────────┴─────────────────────┘

窗口边界也可以添加到聚合结果中

( df.groupby_dynamic("time", every="1h", include_boundaries=True).agg( [pl.col("time").count()] ) )
shape: (3, 4) ┌─────────────────────┬─────────────────────┬─────────────────────┬────────────┐ │ _lower_boundary ┆ _upper_boundary ┆ time ┆ time_count │ │ --- ┆ --- ┆ --- ┆ --- │ │ datetime ┆ datetime ┆ datetime ┆ u32 │ ╞═════════════════════╪═════════════════════╪═════════════════════╪════════════╡ │ 2021-12-16 00:00:00 ┆ 2021-12-16 01:00:00 ┆ 2021-12-16 00:00:00 ┆ 2 │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┤ │ 2021-12-16 01:00:00 ┆ 2021-12-16 02:00:00 ┆ 2021-12-16 01:00:00 ┆ 2 │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┤ │ 2021-12-16 02:00:00 ┆ 2021-12-16 03:00:00 ┆ 2021-12-16 02:00:00 ┆ 2 │ └─────────────────────┴─────────────────────┴─────────────────────┴────────────┘

当closed=“left”,不应包括区间[下限、上限]的右端

( df.groupby_dynamic("time", every="1h", closed="left").agg( [pl.col("time").count(), pl.col("time").list()] ) )
shape: (3, 3) ┌─────────────────────┬────────────┬─────────────────────────────────────┐ │ time ┆ time_count ┆ time_agg_list │ │ --- ┆ --- ┆ --- │ │ datetime ┆ u32 ┆ list [datetime] │ ╞═════════════════════╪════════════╪═════════════════════════════════════╡ │ 2021-12-16 00:00:00 ┆ 2 ┆ [2021-12-16 00:00:00, 2021-12-16... │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ 2021-12-16 01:00:00 ┆ 2 ┆ [2021-12-16 01:00:00, 2021-12-16... │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ │ 2021-12-16 02:00:00 ┆ 2 ┆ [2021-12-16 02:00:00, 2021-12-16... │ └─────────────────────┴────────────┴─────────────────────────────────────┘

当closed="both",窗口边界处的时间值分为两组。

( df.groupby_dynamic("time", every="1h", closed="both").agg( [pl.col("time").count()] ) )
shape: (3, 2) ┌─────────────────────┬────────────┐ │ time ┆ time_count │ │ --- ┆ --- │ │ datetime ┆ u32 │ ╞═════════════════════╪════════════╡ │ 2021-12-16 00:00:00 ┆ 3 │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┤ │ 2021-12-16 01:00:00 ┆ 3 │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┤ │ 2021-12-16 02:00:00 ┆ 3 │ └─────────────────────┴────────────┘

动态groupbys还可以与普通键上的分组相结合

pl.DataFrame( { "time": pl.date_range( low=datetime(2021, 12, 16), high=datetime(2021, 12, 16, 3), interval="30m", ), "groups": ["a", "a", "a", "b", "b", "a", "a"], } )
shape: (7, 2) ┌─────────────────────┬────────┐ │ time ┆ groups │ │ --- ┆ --- │ │ datetime ┆ str │ ╞═════════════════════╪════════╡ │ 2021-12-16 00:00:00 ┆ a │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┤ │ 2021-12-16 00:30:00 ┆ a │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┤ │ 2021-12-16 01:00:00 ┆ a │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┤ │ 2021-12-16 01:30:00 ┆ b │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┤ │ 2021-12-16 02:00:00 ┆ b │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┤ │ 2021-12-16 02:30:00 ┆ a │ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┤ │ 2021-12-16 03:00:00 ┆ a │ └─────────────────────┴────────┘
( df.groupby_dynamic( "time", every="1h", closed="both", by="groups", include_boundaries=True, ).agg([pl.col("time").count()]) )
shape: (4, 5) ┌────────┬─────────────────────┬─────────────────────┬─────────────────────┬────────────┐ │ groups ┆ _lower_boundary ┆ _upper_boundary ┆ time ┆ time_count │ │ --- ┆ --- ┆ --- ┆ --- ┆ --- │ │ str ┆ datetime ┆ datetime ┆ datetime ┆ u32 │ ╞════════╪═════════════════════╪═════════════════════╪═════════════════════╪════════════╡ │ a ┆ 2021-12-16 00:00:00 ┆ 2021-12-16 01:00:00 ┆ 2021-12-16 00:00:00 ┆ 3 │ ├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┤ │ a ┆ 2021-12-16 01:00:00 ┆ 2021-12-16 02:00:00 ┆ 2021-12-16 01:00:00 ┆ 1 │ ├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┤ │ a ┆ 2021-12-16 02:00:00 ┆ 2021-12-16 03:00:00 ┆ 2021-12-16 02:00:00 ┆ 2 │ ├╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┤ │ b ┆ 2021-12-16 01:00:00 ┆ 2021-12-16 02:00:00 ┆ 2021-12-16 01:00:00 ┆ 2 │ └────────┴─────────────────────┴─────────────────────┴─────────────────────┴────────────┘