[Python] Interpolate time series data from one df to time axis of another df in Python polars

Discussão em 'Python' iniciado por Stack, Outubro 1, 2024.

  1. Stack

    Stack Membro Participativo

    I have time series data on different time axes in different dataframes. I need to interpolate data from one df to onto the time axis of another df, df_ref. Ex:

    import polars as pl

    # DataFrame with the reference time axis:
    df_ref = pl.DataFrame({"dt": ["2022-12-14T14:00:01.000", "2022-12-14T14:00:02.000",
    "2022-12-14T14:00:03.000", "2022-12-14T14:00:04.000",
    "2022-12-14T14:00:05.000", "2022-12-14T14:00:06.000"]})
    df_ref = df_ref.with_columns(pl.col("dt").str.to_datetime())

    # DataFrame with a different frequency time axis, to be interpolated onto the reference time axis:
    df = pl.DataFrame({
    "dt": ["2022-12-14T14:00:01.500", "2022-12-14T14:00:03.500", "2022-12-14T14:00:05.500"],
    "v1": [1.5, 3.5, 5.5]})
    df = df.with_columns(pl.col("dt").str.to_datetime())


    I cannot join the dfs since keys don't match:

    print(df_ref.join(df, on="dt", how="left").interpolate())
    shape: (6, 2)
    ┌─────────────────────┬──────┐
    │ dt ┆ v1 │
    │ --- ┆ --- │
    │ datetime[μs] ┆ f64 │
    ╞═════════════════════╪══════╡
    │ 2022-12-14 14:00:01 ┆ null │
    │ 2022-12-14 14:00:02 ┆ null │
    │ 2022-12-14 14:00:03 ┆ null │
    │ 2022-12-14 14:00:04 ┆ null │
    │ 2022-12-14 14:00:05 ┆ null │
    │ 2022-12-14 14:00:06 ┆ null │
    └─────────────────────┴──────┘


    So my 'iterative' approach would be to interpolate each column individually, for instance like

    from scipy.interpolate import interp1d

    f = interp1d(df["dt"].dt.timestamp(), df["v1"],
    kind="linear", bounds_error=False, fill_value="extrapolate")

    out = f(df_ref["dt"].dt.timestamp())
    df_ref = df_ref.with_columns(pl.Series(out).alias("v1_interp"))

    print(df_ref.head(6))
    shape: (6, 2)
    ┌─────────────────────┬───────────┐
    │ dt ┆ v1_interp │
    │ --- ┆ --- │
    │ datetime[μs] ┆ f64 │
    ╞═════════════════════╪═══════════╡
    │ 2022-12-14 14:00:01 ┆ 1.0 │
    │ 2022-12-14 14:00:02 ┆ 2.0 │
    │ 2022-12-14 14:00:03 ┆ 3.0 │
    │ 2022-12-14 14:00:04 ┆ 4.0 │
    │ 2022-12-14 14:00:05 ┆ 5.0 │
    │ 2022-12-14 14:00:06 ┆ 6.0 │
    └─────────────────────┴───────────┘


    Although this gives the result I need, I wonder if there is a more idiomatic approach? I hesitate to mention efficiency here since I haven't benchmarked this with real data yet ("measure, don't guess!"). However, I'd assume that a native implementation in the underlying Rust code could add some performance benefits.

    Continue reading...

Compartilhe esta Página