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

如何在Polars中实现两展开列的Left Join以获取目标结果

用Polars实现列表展开后的左连接匹配

给定如下Polars DataFrame,a列为整数列表,b列为结构体列表:

import polars as pl
df = pl.DataFrame({
    "a": [[1, 2], [3]],
    "b": [
        [{"id": 1, "x": 1}, {"id": 3, "x": 3}],
        [{"id": 3, "x": 4}]
     ]
})

数据结构如下:

┌───────────┬─────────────────┐
│ a         ┆ b               │
│ ---       ┆ ---             │
│ list[i64] ┆ list[struct[2]] │
╞═══════════╪═════════════════╡
│ [1, 2]    ┆ [{1,1}, {3,3}]  │
│ [3]       ┆ [{3,4}]         │
└───────────┴─────────────────┘

需求是:

  1. 将a列展开,每个元素对应一行
  2. 若b列的结构体列表中存在id等于a元素的项,则将对应x值填入b列
  3. 否则b列值为null

原来通过两次explode再过滤的方式得到的是内连接结果,丢失了a=2这类无匹配的行。要实现类似左连接的效果,可以用以下高效方法:

方法一:列表内筛选匹配项

先展开a列,再对每行的b列表筛选出id匹配当前a的结构体,提取x值后取第一个(无匹配则返回null):

result = df.explode("a").with_columns(
    pl.col("b")
    .list.eval(pl.element().struct.field("x").filter(pl.element().struct.field("id") == pl.col("a")))
    .list.first()
    .alias("b")
)

print(result)

方法二:转字典后直接取值

利用struct.to_dict将结构体列表转换为以id为键、x为值的字典,再通过list.get根据a的值获取对应x(不存在则自动返回null):

result = df.explode("a").with_columns(
    pl.col("b")
    .list.struct.to_dict("id", "x")
    .list.get(pl.col("a"))
    .alias("b")
)

print(result)

两种方法都能得到期望的结果:

┌─────┬──────┐
│ a   ┆ b    │
│ --- ┆ ---  │
│ i64 ┆ i64  │
╞═════╪══════╡
│ 1   ┆ 1    │
│ 2   ┆ null │
│ 3   ┆ 4    │
└─────┴──────┘

这两种方式无需生成大量中间行,直接在原行内完成匹配,性能比两次explode后过滤更高效,尤其适合处理大规模数据。

内容的提问来源于stack exchange,提问作者Filippo Vitale

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 16:00:57