重采样

我们可以通过下面几种方式来重新采样, 改变采样间隔

  • upsampling(上采样)
  • downsampling(下采样)
  • 组合(比如先上采样再下采样)

下采样到更低频率

可以视为group_by操作的特例, 可以使用group_by_dynamicgroup_by_rolling来实现这一点

上采样到更高频率

我们生成一个30分钟间隔的数据来讲解

1df = pl.DataFrame(
2    {
3        "time": pl.datetime_range(
4            start=datetime(2021, 12, 16),
5            end=datetime(2021, 12, 16, 3),
6            interval="30m",
7            eager=True,
8        ),
9        "groups": ["a", "a", "a", "b", "b", "a", "a"],
10        "values": [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0],
11    }
12)
13print(df)
1shape: (7, 3)
2┌─────────────────────┬────────┬────────┐
3│ time                ┆ groups ┆ values │
4│ ---                 ┆ ---    ┆ ---    │
5│ datetime[μs]        ┆ str    ┆ f64    │
6╞═════════════════════╪════════╪════════╡
7│ 2021-12-16 00:00:00 ┆ a      ┆ 1.0    │
8│ 2021-12-16 00:30:00 ┆ a      ┆ 2.0    │
9│ 2021-12-16 01:00:00 ┆ a      ┆ 3.0    │
10│ 2021-12-16 01:30:00 ┆ b      ┆ 4.0    │
11│ 2021-12-16 02:00:00 ┆ b      ┆ 5.0    │
12│ 2021-12-16 02:30:00 ┆ a      ┆ 6.0    │
13│ 2021-12-16 03:00:00 ┆ a      ┆ 7.0    │
14└─────────────────────┴────────┴────────┘

上采样可以通过定义新的采样间隔来完成. 通过上采样, 我们在没有数据的地方添加额外的行. 因此上采样会生成一个包含空值的DataFrame, 这些空值可以通过填充策略或插值来填充

上采样策略

在这个例子中, 我们将原始的30分钟上采样到15分钟, 然后使用forward策略将空值替换为前一个非空值

1out1 = df.upsample(time_column="time", every="15m").fill_null(strategy="forward")
2print(out1)
1shape: (13, 3)
2┌─────────────────────┬────────┬────────┐
3│ time                ┆ groups ┆ values │
4│ ---                 ┆ ---    ┆ ---    │
5│ datetime[μs]        ┆ str    ┆ f64    │
6╞═════════════════════╪════════╪════════╡
7│ 2021-12-16 00:00:00 ┆ a      ┆ 1.0    │
8│ 2021-12-16 00:15:00 ┆ a      ┆ 1.0    │
9│ 2021-12-16 00:30:00 ┆ a      ┆ 2.0    │
10│ 2021-12-16 00:45:00 ┆ a      ┆ 2.0    │
11│ 2021-12-16 01:00:00 ┆ a      ┆ 3.0    │
12│ …                   ┆ …      ┆ …      │
13│ 2021-12-16 02:00:00 ┆ b      ┆ 5.0    │
14│ 2021-12-16 02:15:00 ┆ b      ┆ 5.0    │
15│ 2021-12-16 02:30:00 ┆ a      ┆ 6.0    │
16│ 2021-12-16 02:45:00 ┆ a      ┆ 6.0    │
17│ 2021-12-16 03:00:00 ┆ a      ┆ 7.0    │
18└─────────────────────┴────────┴────────┘

下面这个例子中我们通过线性插值来填充空值

1out2 = (
2    df.upsample(time_column="time", every="15m")
3    .interpolate()
4    .fill_null(strategy="forward")
5)
6print(out2)
1shape: (13, 3)
2┌─────────────────────┬────────┬────────┐
3│ time                ┆ groups ┆ values │
4│ ---                 ┆ ---    ┆ ---    │
5│ datetime[μs]        ┆ str    ┆ f64    │
6╞═════════════════════╪════════╪════════╡
7│ 2021-12-16 00:00:00 ┆ a      ┆ 1.0    │
8│ 2021-12-16 00:15:00 ┆ a      ┆ 1.5    │
9│ 2021-12-16 00:30:00 ┆ a      ┆ 2.0    │
10│ 2021-12-16 00:45:00 ┆ a      ┆ 2.5    │
11│ 2021-12-16 01:00:00 ┆ a      ┆ 3.0    │
12│ …                   ┆ …      ┆ …      │
13│ 2021-12-16 02:00:00 ┆ b      ┆ 5.0    │
14│ 2021-12-16 02:15:00 ┆ b      ┆ 5.5    │
15│ 2021-12-16 02:30:00 ┆ a      ┆ 6.0    │
16│ 2021-12-16 02:45:00 ┆ a      ┆ 6.5    │
17│ 2021-12-16 03:00:00 ┆ a      ┆ 7.0    │
18└─────────────────────┴────────┴────────┘