比较 Polars 中的 2 个表,并根据该比较选择一个值



我在极坐标中有这样的表格:

<th style="text-align: left;">arrival_timeTrain
08:40:10112
19:31:26134

Polars 有join_asof它连接到最接近的键forwardbackward时间。


from datetime import time
df_a = pl.DataFrame({
"arrival_time": [time(8, 40, 10), time(19, 31, 26)],
"train": [112, 134]
})
df_b = pl.DataFrame({
"arrival_time": [time(8), time(16)],
"period": ["early", "afternoon"]

})
print(df_a.join_asof(df_b, on="arrival_time"))
shape: (2, 3)
┌──────────────┬───────┬───────────┐
│ arrival_time ┆ train ┆ period    │
│ ---          ┆ ---   ┆ ---       │
│ time         ┆ i64   ┆ str       │
╞══════════════╪═══════╪═══════════╡
│ 08:40:10     ┆ 112   ┆ early     │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
│ 19:31:26     ┆ 134   ┆ afternoon │
└──────────────┴───────┴───────────┘

构建@ritchie46答案,如果您需要找到最接近的值,则可以在向前和向后方向上应用join_asof,并选择最接近的结果。

例如,如果我们从这些数据开始:

df_a = pl.DataFrame(
{"arrival_time": [time(8, 40, 10), time(8, 59, 0), time(
19, 31, 26)], "train": [112, 113, 134]}
)
df_b = pl.DataFrame(
{
"arrival_time": [
time(8),
time(8, 30, 0),
time(9),
time(16),
time(16, 30, 0),
time(17),
],
"period": [
"early morning",
"mid-morning",
"late morning",
"early afternoon",
"mid afternoon",
"late afternoon",
],
}
)
df_a
df_b
shape: (3, 2)
┌──────────────┬───────┐
│ arrival_time ┆ train │
│ ---          ┆ ---   │
│ time         ┆ i64   │
╞══════════════╪═══════╡
│ 08:40:10     ┆ 112   │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┤
│ 08:59:00     ┆ 113   │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┤
│ 19:31:26     ┆ 134   │
└──────────────┴───────┘
>>> df_b
shape: (6, 2)
┌──────────────┬─────────────────┐
│ arrival_time ┆ period          │
│ ---          ┆ ---             │
│ time         ┆ str             │
╞══════════════╪═════════════════╡
│ 08:00:00     ┆ early morning   │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ 08:30:00     ┆ mid-morning     │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ 09:00:00     ┆ late morning    │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ 16:00:00     ┆ early afternoon │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ 16:30:00     ┆ mid afternoon   │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ 17:00:00     ┆ late afternoon  │
└──────────────┴─────────────────┘

我们看到火车113更接近late morning而不是mid-morning。 如果需要捕获它,可以同时加入backwardforward,然后选择最接近的:

(
df_a
.join_asof(df_b.with_column(pl.col('arrival_time').alias('early_time')), on="arrival_time", strategy="backward", suffix="_early")
.join_asof(df_b.with_column(pl.col('arrival_time').alias('late_time')), on="arrival_time", strategy="forward", suffix="_late")
.with_column(
pl.when(pl.col('early_time').is_null())
.then(pl.col('period_late'))
.when(pl.col('late_time').is_null())
.then(pl.col('period'))
.when((pl.col('arrival_time').cast(pl.Datetime) - pl.col('early_time').cast(pl.Datetime)) <
(pl.col('late_time').cast(pl.Datetime) - pl.col('arrival_time').cast(pl.Datetime)))
.then(pl.col('period'))
.otherwise(pl.col('period_late'))
.alias('closest')
)
)
shape: (3, 7)
┌──────────────┬───────┬────────────────┬────────────┬──────────────┬───────────┬────────────────┐
│ arrival_time ┆ train ┆ period         ┆ early_time ┆ period_late  ┆ late_time ┆ closest        │
│ ---          ┆ ---   ┆ ---            ┆ ---        ┆ ---          ┆ ---       ┆ ---            │
│ time         ┆ i64   ┆ str            ┆ time       ┆ str          ┆ time      ┆ str            │
╞══════════════╪═══════╪════════════════╪════════════╪══════════════╪═══════════╪════════════════╡
│ 08:40:10     ┆ 112   ┆ mid-morning    ┆ 08:30:00   ┆ late morning ┆ 09:00:00  ┆ mid-morning    │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ 08:59:00     ┆ 113   ┆ mid-morning    ┆ 08:30:00   ┆ late morning ┆ 09:00:00  ┆ late morning   │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ 19:31:26     ┆ 134   ┆ late afternoon ┆ 17:00:00   ┆ null         ┆ null      ┆ late afternoon │
└──────────────┴───────┴────────────────┴────────────┴──────────────┴───────────┴────────────────┘

请注意,在when/then/otherwise中,我选择明确处理火车在第一个周期之前或最后一个周期之后到达的情况。

最新更新