如果列值在其他列中,则极坐标连接两个数据框

问题描述 投票:0回答:2

如果一列的值包含在另一列中,我想加入两个数据框。 数据框如下所示:

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"]})

我尝试这样做:

model_data = df1.join(df2, on="col2")

这不会产生预期的结果。 我希望看到的是这样的:

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   │
└──────┴────────────┴──────┴──────┘

这是一个当一个值被另一个值包含时如何进行连接的问题。 我在文档中找不到这方面的好例子。

python python-polars
2个回答
5
投票

您想要将

col2
.explode()
类似于 python-polars 通过分隔符将字符串列拆分为许多列

然后您可以执行

.join()

>>> (df1.with_column(df1["col2"].str.split(", ").alias("col4"))
...    .explode("col4")
...    .join(df2, on="col4")
...    .select(df1.columns + df2.columns))
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   │
└──────┴────────────┴──────┴──────┘

2
投票

另一种可能更快的方法是在它们之间进行交叉连接,然后过滤掉 col4

 不在 
col2
 中的时间

看起来像这样...

cj = df1.join(df2, how='cross') filt = cj.apply(lambda x: x[3] in x[1]) ( cj.with_column(filt.to_series().alias('filt')) .filter(pl.col('filt') == True) .select(pl.exclude('filt')) )
本质上,您创建了 

cj

,这是一个将 df1 和 df2 的每一行混合在一起的 df。  然后,您创建 
filt
,它只是一系列可供您过滤的真值和假值。  您可以按此进行过滤,然后进行选择以排除该帮助列。  您只需小心第二行 lambda 表达式中的索引位置即可。

您必须测试此方法与@jqurious 方法的性能。 如果(如果,我不知道)这个更快,那是因为

str.split.explode

 并不像将所有东西混在一起那么有效。  不幸的是, 
series.str.contains
 方法正在寻找固定的正则表达式或文字,因此这就是使用 lambda 的原因。

© www.soinside.com 2019 - 2024. All rights reserved.