Skip to content

リサンプリング

データは以下のいずれかの方法でリサンプリングできます:

  • アップサンプリング(データを高頻度にする)
  • ダウンサンプリング(データを低頻度にする)
  • これらの組み合わせ、例えばまずアップサンプリングしてからダウンサンプリングする

低頻度へのダウンサンプリング

Polars では、ダウンサンプリングを group_by 操作の特殊なケースとして扱っており、group_by_dynamicgroup_by_rolling を使って行うことができます - 時系列 group by のページを参照してください

高頻度へのアップサンプリング

30 分間隔のデータを生成する例を見てみましょう:

DataFrame · date_range

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 · Available on feature range · Available on feature dtype-date

let time = polars::time::date_range(
    "time",
    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 が得られます。これらの null 値は、埋め込み戦略や補間を使って埋めることができます。

アップサンプリング戦略

この例では、元の 30 分から 15 分にアップサンプリングし、その後 forward 戦略を使って null 値を前の非 null 値で置き換えています:

upsample

out1 = df.upsample(time_column="time", every="15m").fill_null(strategy="forward")
print(out1)

upsample

let out1 = df
    .clone()
    .upsample::<[String; 0]>([], "time", Duration::parse("15m"), Duration::parse("0"))?
    .fill_null(FillNullStrategy::Forward(None))?;
println!("{}", &out1);

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    │
└─────────────────────┴────────┴────────┘

この例では、代わりに null 値を線形補間で埋めています:

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"), Duration::parse("0"))?
    .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    │
└─────────────────────┴────────┴────────┘