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

如何在Polars中实现仅保留组合的交叉连接(无需先生成全组合)

如何在Polars中高效生成两列的组合(非排列)结果,无需先做全交叉连接?

我需要连接两个完全相同的列,仅保留组合(而非排列)结果(即只保留a < b的行)。目前的实现是先执行全交叉连接再过滤,代码如下:

import polars as pl

df1 = pl.DataFrame({"a": range(3)})
df2 = pl.DataFrame({"b": range(3)})

expected_output = df1.join(df2, how="cross").filter(pl.col("a") < pl.col("b"))

预期输出为:

shape: (3, 2)
┌─────┬─────┐
│ a   ┆ b   │
│ --- ┆ --- │
│ i32 ┆ i32 │
╞═════╪═════╡
│ 0   ┆ 1   │
│ 0   ┆ 2   │
│ 1   ┆ 2   │
└─────┴─────┘

请问有没有不需要先生成全组合的实现方法?


当然有,你可以直接生成符合a < b条件的索引对,再映射到原数据,避免全量交叉连接带来的性能开销,数据量越大,这种方式的优势越明显。

方法1:索引映射法(推荐)

通过行索引生成合法的组合对,再关联原数据:

import polars as pl

# 用单个DataFrame替代两个相同的df,减少冗余
df = pl.DataFrame({"val": range(3)})

result = df.with_row_index("idx").select(
    pl.col("val").alias("a"),
    # 对每个行索引,生成从idx+1到末尾的索引序列并展开
    pl.int_range(pl.col("idx") + 1, len(df)).explode().alias("b_idx")
).join(df.with_row_index("idx"), left_on="b_idx", right_on="idx") \
 .select("a", pl.col("val").alias("b"))

执行结果与预期一致:

shape: (3, 2)
┌─────┬─────┐
│ a   ┆ b   │
│ --- ┆ --- │
│ i32 ┆ i32 │
╞═════╪═════╡
│ 0   ┆ 1   │
│ 0   ┆ 2   │
│ 1   ┆ 2   │
└─────┴─────┘

方法2:窗口函数法

如果数据本身是有序的,也可以用窗口函数结合explode实现,但性能不如索引映射法:

import polars as pl

df = pl.DataFrame({"val": range(3)})

result = df.select(
    pl.col("val").alias("a"),
    pl.col("val").filter(pl.col("val") > pl.col("val").over()).explode().alias("b")
)

性能说明

当数据量较大时(比如1000行),全交叉连接会生成100万行再过滤,而索引映射法直接生成约50万行目标数据,内存占用和执行时间都会大幅降低。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 02:55:01