Polars如何基于列值包含关系实现两个DataFrame的连接?
基于列值包含关系实现Polars DataFrame连接
普通的join操作是精确匹配列值,你之前用df1.join(df2, on="col2")无法得到预期结果,因为df1.col2是逗号分隔的字符串集合,而df2.col4是单个值,需要判断单个值是否属于集合中的成员。
下面提供两种可行的实现方式:
方法1:交叉连接后过滤匹配项
先通过cross_join生成所有可能的行组合,再筛选出col4值存在于col2中的行:
import polars as pl df1 = pl.DataFrame({"col1": [1, 2, 3], "col2": ["x1, x2, x3", "x2, x3", "x3"]}) df2 = pl.DataFrame({"col3": [4, 5, 6], "col4": ["x1", "x2", "x3"]}) result = df1.cross_join(df2).filter( pl.col("col2").str.contains(pl.col("col4"), literal=True) ) print(result)
literal=True确保将col4的值作为纯文本匹配,避免正则表达式的特殊字符干扰。- 优点:代码简洁直观;缺点:会生成笛卡尔积,数据量大时性能较差。
方法2:拆分展开后精确连接
先将df1.col2拆分为列表并展开,再通过精确匹配col4完成连接,这种方式性能更优:
import polars as pl df1 = pl.DataFrame({"col1": [1, 2, 3], "col2": ["x1, x2, x3", "x2, x3", "x3"]}) df2 = pl.DataFrame({"col3": [4, 5, 6], "col4": ["x1", "x2", "x3"]}) # 拆分col2为单个值的列表并展开 df1_exploded = df1.with_columns( pl.col("col2").str.split(", ").alias("matched_col") ).explode("matched_col") # 基于拆分后的列精确连接 result = df1_exploded.join(df2, left_on="matched_col", right_on="col4").drop("matched_col") print(result)
- 优点:避免笛卡尔积,大数据集下性能更高效;缺点:需要多一步拆分展开的操作。
两种方法最终都会输出你期望的结果:
shape: (6, 4) ┌──────┬────────────┬──────┬──────┐ │ col1 ┆ col2 ┆ col3 ┆ col4 │ │ --- ┆ --- ┆ --- ┆ --- │ │ i64 ┆ str ┆ i64 ┆ str │ ╞══════╪════════════╪══════╪══════╡ │ 1 ┆ x1, x2, x3 ┆ 4 ┆ x1 │ │ 1 ┆ x1, x2, x3 ┆ 5 ┆ x2 │ │ 1 ┆ x1, x2, x3 ┆ 6 ┆ x3 │ │ 2 ┆ x2, x3 ┆ 5 ┆ x2 │ │ 2 ┆ x2, x3 ┆ 6 ┆ x3 │ │ 3 ┆ x3 ┆ 6 ┆ x3 │ └──────┴────────────┴──────┴──────┘
内容的提问来源于stack exchange,提问作者Sledge
相关产品推荐
相关产品推荐

