Berechnung des pfadabhängigen Ereignisergebnisses der Polars-ZeitreihePython

Python-Programme
Anonymous
 Berechnung des pfadabhängigen Ereignisergebnisses der Polars-Zeitreihe

Post by Anonymous »

Im Demo-DataFrame habe ich drei Ereignisse:

Code: Select all

import polars as pl

df = pl.DataFrame(
{
"timestamp": [1, 2, 3, 4, 5, 6, 7, 8],
"threshold": [8, None, None, None, 5, None, None, 8],
"value": [2, 3, 4, 5, 6, 7, 8, 9],
"event": [1, 0, 0, 0, 1, 0, 0, 1],
"start_ts": [1, None, None, None, 5, None, None, 8],
"end_ts": [6, None, None, None, 8, None, None, 8],
"event_id": [0, None, None, None, 1, None, None, 2],
}
).with_columns(pl.col("end_ts").sub(pl.col("start_ts")).alias("event_span"))

print(df)

Code: Select all

shape: (8, 8)
┌───────────┬───────────┬───────┬───────┬──────────┬────────┬──────────┬────────────┐
│ timestamp ┆ threshold ┆ value ┆ event ┆ start_ts ┆ end_ts ┆ event_id ┆ event_span │
│ ---       ┆ ---       ┆ ---   ┆ ---   ┆ ---      ┆ ---    ┆ ---      ┆ ---        │
│ i64       ┆ i64       ┆ i64   ┆ i64   ┆ i64      ┆ i64    ┆ i64      ┆ i64        │
╞═══════════╪═══════════╪═══════╪═══════╪══════════╪════════╪══════════╪════════════╡
│ 1         ┆ 8         ┆ 2     ┆ 1     ┆ 1        ┆ 6      ┆ 0        ┆ 5          │
│ 2         ┆ null      ┆ 3     ┆ 0     ┆ null     ┆ null   ┆ null     ┆ null       │
│ 3         ┆ null      ┆ 4     ┆ 0     ┆ null     ┆ null   ┆ null     ┆ null       │
│ 4         ┆ null      ┆ 5     ┆ 0     ┆ null     ┆ null   ┆ null     ┆ null       │
│ 5         ┆ 5         ┆ 6     ┆ 1     ┆ 5        ┆ 8      ┆ 1        ┆ 3          │
│ 6         ┆ null      ┆ 7     ┆ 0     ┆ null     ┆ null   ┆ null     ┆ null       │
│ 7         ┆ null      ┆ 8     ┆ 0     ┆ null     ┆ null   ┆ null     ┆ null       │
│ 8         ┆ 8         ┆ 9     ┆ 1     ┆ 8        ┆ 8      ┆ 2        ┆ 0          │
└───────────┴───────────┴───────┴───────┴──────────┴────────┴──────────┴────────────┘
  • Code: Select all

    timestamp
    ist der Zeitstempel in der realen Welt.
  • Code: Select all

    threshold
    ist der Wert, den der Wert jedes Ereignisses während der Ereignisspanne erreichen oder überschreiten muss.
  • Code: Select all

    value
    ist der Wert bei jedem Zeitstempel, wir können doppelte Werte haben.
  • Code: Select all

    event
    ist eine binäre Spalte, die angibt, ob ein bestimmter Zeitstempel ein Ereignis generiert.
  • Code: Select all

    start_ts
    ist der Startzeitstempel eines Ereignisses. Ein start_ts von 1 bedeutet beispielsweise, dass das Ereignis am Ende von Zeitstempel1 und am Anfang von Zeitstempel2
  • beginnt

    Code: Select all

    end_ts
    ist der Endzeitstempel eines Ereignisses.
  • Code: Select all

    event_id
    ist eine eindeutige Kennung für jedes Ereignis.
  • Code: Select all

    event_span
    ist die Anzahl der Zeitstempel, die ein Ereignis umfasst.
Problem:
Ich möchte Folgendes identifizieren:
  • Code: Select all

    event outcome
    : binärer Wert, der angibt, ob der Schwellenwert jedes Ereignisses durch value während jeder Ereignisspanne erreicht wird.
  • Code: Select all

    event outcome timestamp
    : der Zeitstempel, bei dem der erste Wert den Schwellenwert erreicht
Zusätzlicher Hinweis:
  • Ereignis 0 umfasst [2, 3, 4, 5, 6], Ereignis 1 umfasst [6, 7, 8] und Ereignis 2 umfasst Nichts.
  • Die Ereignisse würden nicht über die Daten hinausgehen, die wir hier haben (z. B. end_ts 0)
    .with_columns(
    pl.int_ranges(pl.col("start_ts")+1, pl.col("end_ts")+1) # Map event full path
    .alias("event_timestamps")
    )
    .explode("event_timestamps") # Generate event full path
    .drop(pl.col("value"))
    .join(
    df
    .select(pl.col("timestamp"), pl.col("value"))
    .rename({"timestamp": "event_timestamps"}),
    on="event_timestamps", how="left") # Get the value of the full path
    .with_columns(# Map event outcome based on threshold
    pl.when(pl.col("value") >= pl.col("threshold"))
    .then(1)
    .otherwise(None)
    .alias("event_outcome")
    )
    .with_columns(# Get event outcome timestamp
    pl.when(pl.col("event_outcome") == 1)
    .then(pl.col("event_timestamps"))
    .otherwise(None)
    .alias("event_outcome_timestamp")
    )
    .with_columns(# Map event outcome to the event start timestamp
    pl.col("event_outcome", "event_outcome_timestamp")
    .fill_null(strategy="backward")
    .over("event_id")
    )
    .unique("event_id")
    .sort("event_id")
    .with_columns(# Take care of the events that have not exceeded the threshold
    pl.when(pl.col("event_outcome").is_null())
    .then(0)
    .otherwise(pl.col("event_outcome"))
    .alias("event_outcome")
    )
    .select(pl.col("event_id", "event_outcome", "event_outcome_timestamp"))
    )

    event_df
    [/code]

    Code: Select all

    shape: (2, 3)
    ┌──────────┬───────────────┬─────────────────────────┐
    │ event_id ┆ event_outcome ┆ event_outcome_timestamp │
    │ ---      ┆ ---           ┆ ---                     │
    │ i64      ┆ i32           ┆ i64                     │
    ╞══════════╪═══════════════╪═════════════════════════╡
    │ 0        ┆ 0             ┆ null                    │
    │ 1        ┆ 1             ┆ 6                       │
    └──────────┴───────────────┴─────────────────────────┘
    

    Code: Select all

    df = df.join(event_df, on="event_id", how="left")
    

Quick Reply

Change Text Case: 
   
  • Similar Topics
    Replies
    Views
    Last post