首頁 >後端開發 >Python教學 >如何基於其他 DataFrame 行過濾器建立列?

如何基於其他 DataFrame 行過濾器建立列?

WBOY
WBOY轉載
2024-02-09 13:30:04568瀏覽

如何基于其他 DataFrame 行过滤器创建列?

問題內容

我有一個名為「hourly_data」的 lazyframe,其中包含一個名為「time」的每小時日期時間列。 我還有一個名為「future_periods」的 dataframe,其中包含兩個日期時間列,稱為「start」(未來週期的開始日期時間)和「end」(未來週期的結束時間)。重要的是,這些未來時期並不重疊。

我想為hourly_data lazyframe 建立一個名為「period」的列,它應該有一個int 值,該值基於哪個週期(future_periods dataframe 行,如果有10 個週期,則從0 到9)時間列值hourly_data 的值介於future_periods 的開始列值和結束列值之間。

我嘗試執行以下操作:

periods = pl.series(range(future_periods.height))
hourly_data = hourly_data.with_columns(
    (
        pl.when(((future_periods.get_column('start') <= pl.col('time')) & (pl.col('time') <= future_periods.get_column('end'))).any())
        .then(periods.filter(pl.series((future_periods.get_column('start') <= pl.col('real_time')) & (pl.col('real_time') <= future_periods.get_column('end')))).to_list()[0])
        .otherwise(none)
    ).alias('period')
)

但這給了我錯誤:typeerror:使用 values 參數的不支援類型「expr」呼叫系列建構子

我想要實現的目標: 輸入:

hourly_data:
┌────────────────────┐
│ time               │
│ ---                │
│ datetime           │
╞════════════════════╡
│ 2024-01-01 00:00:00│
│ 2024-01-01 01:00:00│
│ 2024-01-01 02:00:00│
│         ...        │
│ 2024-03-31 23:00:00│
│ 2024-04-01 00:00:00│
│ 2024-04-01 01:00:00│
│         ...        │
│ 2024-06-01 00:00:00│
└────────────────────┘
future_periods:
┌─────────────────────────┬───────────────────────┐
│ start                   ┆ end                   │
│ ---                     ┆ ---                   │
│ datetime                ┆ datetime              │
╞═════════════════════════╪═══════════════════════╡
│ 2024-01-01 00:00:00     ┆ 2024-01-31 23:00:00   │
│ 2024-02-01 00:00:00     ┆ 2024-02-28 23:00:00   │
│ 2024-03-01 00:00:00     ┆ 2024-03-31 23:00:00   │
│ 2024-04-01 00:00:00     ┆ 2024-05-31 23:00:00   │
└─────────────────────────┴───────────────────────┘

輸出:

hourly_data:
┌─────────────────────────┬────────┐
│ time                    ┆ period │
│ ---                     ┆ ---    │
│ datetime                ┆ int    │
╞═════════════════════════╪════════╡
│ 2024-01-01 00:00:00     ┆ 0      │
│ 2024-01-01 01:00:00     ┆ 0      │
│ 2024-01-01 02:00:00     ┆ 0      │
│          ...            ┆ ...    │
│ 2024-03-31 23:00:00     ┆ 2      │
│ 2024-04-01 00:00:00     ┆ 3      │
│ 2024-04-01 01:00:00     ┆ 3      │
│          ...            ┆ ...    │
│ 2024-06-01 00:00:00     ┆ None   │
└─────────────────────────┴────────┘

正確答案


#一般來說,它是不等式連接,或者在您的情況下,在範圍內連接。這是執行此操作的一種方法。讓我們先創建一些範例資料:

hourly_data = pl.dataframe({
    "time": ['2023-01-01 14:00','2023-01-02 09:00', '2023-01-04 11:00']
}).lazy()

future_periods = pl.dataframe({
    "id": [1,2,3,4],
    "start": ['2023-01-01 11:00','2023-01-02 10:00', '2023-01-03 15:00', '2023-01-04 10:00'],
    "end": ['2023-01-01 16:00','2023-01-02 11:00', '2023-01-03 18:00', '2023-01-04 15:00']
}).lazy()

┌──────────────────┬──────┐
│ time             ┆ data │
│ ---              ┆ ---  │
│ str              ┆ str  │
╞══════════════════╪══════╡
│ 2023-01-01 14:00 ┆ a    │
│ 2023-01-02 09:00 ┆ b    │
│ 2023-01-04 11:00 ┆ c    │
└──────────────────┴──────┘ 
┌─────┬──────────────────┬──────────────────┐
│ id  ┆ start            ┆ end              │
│ --- ┆ ---              ┆ ---              │
│ i64 ┆ str              ┆ str              │
╞═════╪══════════════════╪══════════════════╡
│ 1   ┆ 2023-01-01 11:00 ┆ 2023-01-01 16:00 │
│ 2   ┆ 2023-01-02 10:00 ┆ 2023-01-02 11:00 │
│ 3   ┆ 2023-01-03 15:00 ┆ 2023-01-03 18:00 │
│ 4   ┆ 2023-01-04 10:00 ┆ 2023-01-04 15:00 │
└─────┴──────────────────┴──────────────────┘

現在,您可以分兩步完成 - 首先,計算 time 和未來時段 id 之間的連結:

time_periods = (
   hourly_data
       .join(future_periods, how="cross")
       .filter(
           pl.col("time") > pl.col("start"),
           pl.col("time") < pl.col("end")
        ).select(["time","id"])
)

┌──────────────────┬─────┐
│ time             ┆ id  │
│ ---              ┆ --- │
│ str              ┆ i64 │
╞══════════════════╪═════╡
│ 2023-01-01 14:00 ┆ 1   │
│ 2023-01-04 11:00 ┆ 4   │
└──────────────────┴─────┘

然後您可以將其與原始資料框連接起來:

hourly_data.join(time_periods, how="left", on="time").collect()

┌──────────────────┬──────┬──────┐
│ time             ┆ data ┆ id   │
│ ---              ┆ ---  ┆ ---  │
│ str              ┆ str  ┆ i64  │
╞══════════════════╪══════╪══════╡
│ 2023-01-01 14:00 ┆ a    ┆ 1    │
│ 2023-01-02 09:00 ┆ b    ┆ null │
│ 2023-01-04 11:00 ┆ c    ┆ 4    │
└──────────────────┴──────┴──────┘

執行此操作的另一種方法可能是使用 duckdb 感謝 與 polars 整合

import duckdb
import polars as pl

duckdb.sql("""
    select
        h.time, h.data, p.id
    from hourly_data as h
        left join future_periods as p on
            p.start < h.time and
            p.end > h.time
""").pl()

┌──────────────────┬──────┬──────┐
│ time             ┆ data ┆ id   │
│ ---              ┆ ---  ┆ ---  │
│ str              ┆ str  ┆ i64  │
╞══════════════════╪══════╪══════╡
│ 2023-01-01 14:00 ┆ A    ┆ 1    │
│ 2023-01-04 11:00 ┆ C    ┆ 4    │
│ 2023-01-02 09:00 ┆ B    ┆ null │
└──────────────────┴──────┴──────┘

以上是如何基於其他 DataFrame 行過濾器建立列?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:stackoverflow.com。如有侵權,請聯絡admin@php.cn刪除