You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Polars DataFrame间执行基于不等式条件的连接?

在Polars中实现基于不等式的DataFrame左连接

需要在两个Polars DataFrame之间执行基于m.date >= o.date的左连接,得到与指定SQL语句完全等效的结果。

给定的DataFrame

from datetime import date
import polars as pl

stock_market_value = pl.DataFrame(
    {
        "date": [date(2022, 1, 1), date(2022, 2, 1), date(2022, 3, 1)],
        "price": [10.00, 12.00, 14.00]
    }
)

my_stock_orders = pl.DataFrame(
    {
        "date": [date(2022, 1, 15), date(2022, 2, 15)],
        "quantity": [2, 5] 
    }
)

需求对应的SQL语句

SELECT m.date, m.price * o.quantity AS portfolio_value
FROM stock_market_value m LEFT JOIN my_stock_orders o
  ON m.date >= o.date

期望输出

通过DuckDB执行等效查询得到的结果如下:

duckdb.sql("""
SELECT 
   m.date market_date, 
   o.date order_date, 
   price,
   quantity, 
   price * quantity AS portfolio_value
FROM stock_market_value m LEFT JOIN my_stock_orders o
  ON m.date >= o.date
""").pl()

输出结果:

shape: (4, 5)
┌─────────────┬────────────┬───────┬──────────┬─────────────────┐
│ market_date | order_date | price | quantity | portfolio_value │
│ ---         | ---        | ---   | ---      | ---             │
│ date        | date       | f64   | i64      | f64             │
╞═════════════╪════════════╪═══════╪══════════╪═════════════════╡
│ 2022-01-01  | null       | 10.0  | null     | null            │
│ 2022-02-01  | 2022-01-15 | 12.0  | 2        | 24.0            │
│ 2022-03-01  | 2022-01-15 | 14.0  | 2        | 28.0            │
│ 2022-03-01  | 2022-02-15 | 14.0  | 5        | 70.0            │
└─────────────┴────────────┴───────┴──────────┴─────────────────┘

为什么asof连接不适用

尝试过使用Polars的join_asof方法,但结果不符合预期:

Forward策略的asof连接

result_fwd = stock_market_value.join_asof(
    my_stock_orders, left_on="date", right_on="date", strategy="forward"
)

print(result_fwd)

输出:

shape: (3, 3)
┌────────────┬───────┬──────────┐
│ date       ┆ price ┆ quantity │
│ ---        ┆ ---   ┆ ---      │
│ date       ┆ f64   ┆ i64      │
╞════════════╪═══════╪══════════╡
│ 2022-01-01 ┆ 10.0  ┆ 2        │
│ 2022-02-01 ┆ 12.0  ┆ 5        │
│ 2022-03-01 ┆ 14.0  ┆ null     │
└────────────┴───────┴──────────┘

Backward策略的asof连接

result_bwd = stock_market_value.join_asof(
    my_stock_orders, left_on="date", right_on="date", strategy="backward"
)

print(result_bwd)

输出:

shape: (3, 3)
┌────────────┬───────┬──────────┐
│ date       ┆ price ┆ quantity │
│ ---        ┆ ---   ┆ ---      │
│ date       ┆ f64   ┆ i64      │
╞════════════╪═══════╪══════════╡
│ 2022-01-01 ┆ 10.0  ┆ null     │
│ 2022-02-01 ┆ 12.0  ┆ 2        │
│ 2022-03-01 ┆ 14.0  ┆ 5        │
└────────────┴───────┴──────────┘

可行解决方案

使用Polars的条件左连接,通过join方法的condition参数指定不等式匹配规则,即可实现与目标SQL完全一致的结果:

# 执行非等值左连接
result = stock_market_value.join(
    my_stock_orders,
    how="left",
    condition=pl.col("date", side="left") >= pl.col("date", side="right")
).rename(
    {"date": "market_date", "date_right": "order_date"}
).with_columns(
    (pl.col("price") * pl.col("quantity")).alias("portfolio_value")
)

print(result)

执行后输出:

shape: (4, 5)
┌─────────────┬────────────┬───────┬──────────┬─────────────────┐
│ market_date │ order_date │ price │ quantity │ portfolio_value │
│ ---         │ ---        │ ---   │ ---      │ ---             │
│ date        │ date       │ f64   │ i64      │ f64             │
╞═════════════╪════════════╪═══════╪══════════╪═════════════════╡
│ 2022-01-01  │ null       │ 10.0  │ null     │ null            │
│ 2022-02-01  │ 2022-01-15 │ 12.0  │ 2        │ 24.0            │
│ 2022-03-01  │ 2022-01-15 │ 14.0  │ 2        │ 28.0            │
│ 2022-03-01  │ 2022-02-15 │ 14.0  │ 5        │ 70.0            │
└─────────────┴────────────┴───────┴──────────┴─────────────────┘

内容的提问来源于stack exchange,提问作者Ameba Spugnosa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 05:55:16