如何用Polars DataFrame实现每行选一个元素的全组合?
用Polars原生方法生成元素的所有组合
要实现从每列的行中选取一个元素的所有可能组合,完全可以用Polars内置的pl.cartesian_product函数或者交叉连接(cross_join)来实现,避免Python循环的性能损耗。
方法一:使用pl.cartesian_product(推荐)
这个函数专门用于生成多个序列的笛卡尔积,直接传入各列的Series即可,代码简洁高效:
import polars as pl # 构造示例输入DataFrame df = pl.DataFrame({ "Column A": ["A1", "A2", "A3"], "Column B": ["B1", "B2", "B3"], "Column C": ["C1", "C2", "C3"] }) # 生成所有组合 result = pl.DataFrame( pl.cartesian_product([df[col] for col in df.columns]), schema=df.columns ) print(result)
输出结果会包含所有3^3=27种组合,示例片段如下:
shape: (27, 3) ┌──────────┬──────────┬──────────┐ │ Column A ┆ Column B ┆ Column C │ │ --- ┆ --- ┆ --- │ │ str ┆ str ┆ str │ ╞══════════╪══════════╪══════════╡ │ A1 ┆ B1 ┆ C1 │ │ A1 ┆ B1 ┆ C2 │ │ A1 ┆ B1 ┆ C3 │ │ A1 ┆ B2 ┆ C1 │ │ ... ┆ ... ┆ ... │ │ A3 ┆ B3 ┆ C3 │ └──────────┴──────────┴──────────┘
方法二:使用cross_join + fold
如果需要逐步构建交叉连接,可以用pl.fold累积调用cross_join,适合需要自定义中间步骤的场景:
# 将每列转为单独的DataFrame col_dfs = [pl.DataFrame({col: df[col]}) for col in df.columns] # 累积交叉连接生成所有组合 result = pl.fold( acc=col_dfs[0], function=lambda acc, curr_df: acc.cross_join(curr_df), exprs=col_dfs[1:] )
为什么比循环高效?
Polars的原生操作都是基于向量化引擎实现的,完全避开了Python层面的循环开销,当数据量较大(比如列数更多、行数上万)时,性能提升会非常明显。
内容的提问来源于stack exchange,提问作者Ryan Xu
相关产品推荐
相关产品推荐

