重采样
我们可以通过以下方式进行重采样:
- 上采样(将数据移动到更高的频率)
- 下采样(将数据移动到更低的频率)
- 这些的组合,例如先上采样再下采样
下采样到较低的频率
Polars 将下采样视为 group_by 操作的一种特殊情况,您可以使用 group_by_dynamic
和 group_by_rolling
来实现 - 有关示例请参阅时间分组页面。
上采样到较高的频率
让我们看一个以 30 分钟间隔生成数据的例子
df = pl.DataFrame(
{
"time": pl.datetime_range(
start=datetime(2021, 12, 16),
end=datetime(2021, 12, 16, 3),
interval="30m",
eager=True,
),
"groups": ["a", "a", "a", "b", "b", "a", "a"],
"values": [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0],
}
)
print(df)
DataFrame
· date_range
· 在 feature range 上可用 · 在 feature dtype-date 上可用
let time = polars::time::date_range(
"time".into(),
NaiveDate::from_ymd_opt(2021, 12, 16)
.unwrap()
.and_hms_opt(0, 0, 0)
.unwrap(),
NaiveDate::from_ymd_opt(2021, 12, 16)
.unwrap()
.and_hms_opt(3, 0, 0)
.unwrap(),
Duration::parse("30m"),
ClosedWindow::Both,
TimeUnit::Milliseconds,
None,
)?;
let df = df!(
"time" => time,
"groups" => &["a", "a", "a", "b", "b", "a", "a"],
"values" => &[1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0],
)?;
println!("{}", &df);
shape: (7, 3)
┌─────────────────────┬────────┬────────┐
│ time ┆ groups ┆ values │
│ --- ┆ --- ┆ --- │
│ datetime[μs] ┆ str ┆ f64 │
╞═════════════════════╪════════╪════════╡
│ 2021-12-16 00:00:00 ┆ a ┆ 1.0 │
│ 2021-12-16 00:30:00 ┆ a ┆ 2.0 │
│ 2021-12-16 01:00:00 ┆ a ┆ 3.0 │
│ 2021-12-16 01:30:00 ┆ b ┆ 4.0 │
│ 2021-12-16 02:00:00 ┆ b ┆ 5.0 │
│ 2021-12-16 02:30:00 ┆ a ┆ 6.0 │
│ 2021-12-16 03:00:00 ┆ a ┆ 7.0 │
└─────────────────────┴────────┴────────┘
上采样可以通过定义新的采样间隔来完成。通过上采样,我们会在没有数据的地方添加额外的行。因此,上采样本身会产生一个包含空值 (null) 的 DataFrame。这些空值可以通过填充策略或插值来填充。
上采样策略
在此示例中,我们将原始的 30 分钟数据上采样到 15 分钟,然后使用 forward
策略将空值替换为前一个非空值
shape: (13, 3)
┌─────────────────────┬────────┬────────┐
│ time ┆ groups ┆ values │
│ --- ┆ --- ┆ --- │
│ datetime[μs] ┆ str ┆ f64 │
╞═════════════════════╪════════╪════════╡
│ 2021-12-16 00:00:00 ┆ a ┆ 1.0 │
│ 2021-12-16 00:15:00 ┆ a ┆ 1.0 │
│ 2021-12-16 00:30:00 ┆ a ┆ 2.0 │
│ 2021-12-16 00:45:00 ┆ a ┆ 2.0 │
│ 2021-12-16 01:00:00 ┆ a ┆ 3.0 │
│ … ┆ … ┆ … │
│ 2021-12-16 02:00:00 ┆ b ┆ 5.0 │
│ 2021-12-16 02:15:00 ┆ b ┆ 5.0 │
│ 2021-12-16 02:30:00 ┆ a ┆ 6.0 │
│ 2021-12-16 02:45:00 ┆ a ┆ 6.0 │
│ 2021-12-16 03:00:00 ┆ a ┆ 7.0 │
└─────────────────────┴────────┴────────┘
在此示例中,我们转而通过线性插值填充空值
upsample
· interpolate
· fill_null
out2 = (
df.upsample(time_column="time", every="15m")
.interpolate()
.fill_null(strategy="forward")
)
print(out2)
upsample
· interpolate
· fill_null
let out2 = df
.clone()
.upsample::<[String; 0]>([], "time", Duration::parse("15m"))?
.lazy()
.with_columns([col("values").interpolate(InterpolationMethod::Linear)])
.collect()?
.fill_null(FillNullStrategy::Forward(None))?;
println!("{}", &out2);
shape: (13, 3)
┌─────────────────────┬────────┬────────┐
│ time ┆ groups ┆ values │
│ --- ┆ --- ┆ --- │
│ datetime[μs] ┆ str ┆ f64 │
╞═════════════════════╪════════╪════════╡
│ 2021-12-16 00:00:00 ┆ a ┆ 1.0 │
│ 2021-12-16 00:15:00 ┆ a ┆ 1.5 │
│ 2021-12-16 00:30:00 ┆ a ┆ 2.0 │
│ 2021-12-16 00:45:00 ┆ a ┆ 2.5 │
│ 2021-12-16 01:00:00 ┆ a ┆ 3.0 │
│ … ┆ … ┆ … │
│ 2021-12-16 02:00:00 ┆ b ┆ 5.0 │
│ 2021-12-16 02:15:00 ┆ b ┆ 5.5 │
│ 2021-12-16 02:30:00 ┆ a ┆ 6.0 │
│ 2021-12-16 02:45:00 ┆ a ┆ 6.5 │
│ 2021-12-16 03:00:00 ┆ a ┆ 7.0 │
└─────────────────────┴────────┴────────┘