极坐标 >= 0.18.10
对列表使用集合操作:
df.select(
intersection = pl.col('a').list.set_intersection('b'),
difference = pl.col('a').list.set_difference('b'),
union = pl.col('a').list.set_union('b')
)
极坐标 >= 0.18.5,极坐标
对列表使用集合操作(使用旧名称):
df.select(
intersection = pl.col('a').list.intersection('b'),
difference = pl.col('a').list.difference('b'),
union = pl.col('a').list.union('b')
)
极坐标
我们可以使用以下方法完成交集arr.eval表达。这arr.eval
表达式允许我们将列表视为系列/列,以便我们可以使用与列和系列相同的上下文和表达式。
首先,让我们扩展您的示例,以便我们可以展示当交集为空时会发生什么。
df = pl.DataFrame(
{
"a": [[1, 2, 3], [8, 9, 4], [0, 1, 2]],
"b": [[2, 3, 4], [4, 5, 6], [10, 11, 12]],
}
)
df
shape: (3, 2)
┌───────────┬──────────────┐
│ a ┆ b │
│ --- ┆ --- │
│ list[i64] ┆ list[i64] │
╞═══════════╪══════════════╡
│ [1, 2, 3] ┆ [2, 3, 4] │
├╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ [8, 9, 4] ┆ [4, 5, 6] │
├╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ [0, 1, 2] ┆ [10, 11, 12] │
└───────────┴──────────────┘
算法
有两种方法可以实现此目的。第一个可扩展到两个以上集合的交集(参见下面的其他注释)。
df.with_column(
pl.col("a")
.arr.concat('b')
.arr.eval(pl.element().filter(pl.count().over(pl.element()) == 2))
.arr.unique()
.alias('intersection')
)
or
df.with_column(
pl.col("a")
.arr.concat('b')
.arr.eval(pl.element().filter(pl.element().is_duplicated()))
.arr.unique()
.alias('intersection')
)
shape: (3, 3)
┌───────────┬──────────────┬──────────────┐
│ a ┆ b ┆ intersection │
│ --- ┆ --- ┆ --- │
│ list[i64] ┆ list[i64] ┆ list[i64] │
╞═══════════╪══════════════╪══════════════╡
│ [1, 2, 3] ┆ [2, 3, 4] ┆ [2, 3] │
├╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ [8, 9, 4] ┆ [4, 5, 6] ┆ [4] │
├╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ [0, 1, 2] ┆ [10, 11, 12] ┆ [] │
└───────────┴──────────────┴──────────────┘
怎么运行的
我们首先将两个列表连接成一个列表。两个列表中的任何元素都会出现两次。
df.with_column(
pl.col("a")
.arr.concat('b')
.alias('ablist')
)
shape: (3, 3)
┌───────────┬──────────────┬────────────────┐
│ a ┆ b ┆ ablist │
│ --- ┆ --- ┆ --- │
│ list[i64] ┆ list[i64] ┆ list[i64] │
╞═══════════╪══════════════╪════════════════╡
│ [1, 2, 3] ┆ [2, 3, 4] ┆ [1, 2, ... 4] │
├╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ [8, 9, 4] ┆ [4, 5, 6] ┆ [8, 9, ... 6] │
├╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ [0, 1, 2] ┆ [10, 11, 12] ┆ [0, 1, ... 12] │
└───────────┴──────────────┴────────────────┘
然后我们可以使用arr.eval
函数允许我们将串联列表视为一个系列/列。在这种情况下,我们将使用filter
context 来查找任何出现多次的元素。 (这polars.element列表上下文中的表达式的用法如下polars.col
在系列中使用。)
df.with_column(
pl.col("a")
.arr.concat('b')
.arr.eval(pl.element().filter(pl.count().over(pl.element()) == 2))
.alias('filtered')
)
shape: (3, 3)
┌───────────┬──────────────┬───────────────┐
│ a ┆ b ┆ filtered │
│ --- ┆ --- ┆ --- │
│ list[i64] ┆ list[i64] ┆ list[i64] │
╞═══════════╪══════════════╪═══════════════╡
│ [1, 2, 3] ┆ [2, 3, 4] ┆ [2, 3, ... 3] │
├╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ [8, 9, 4] ┆ [4, 5, 6] ┆ [4, 4] │
├╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ [0, 1, 2] ┆ [10, 11, 12] ┆ [] │
└───────────┴──────────────┴───────────────┘
注:上述步骤也可以用is_duplicated表达。 (在其他注释部分,我们将看到使用is_duplicated
当计算两个以上集合的交集时将不起作用。)
df.with_column(
pl.col("a")
.arr.concat('b')
.arr.eval(pl.element().filter(pl.element().is_duplicated()))
.alias('filtered')
)
剩下的就是使用以下方法从结果中删除重复项arr.unique
表达式(这是开头所示的结果)。
其他注意事项
我假设您的列表确实是集合,因为元素在每个列表中仅出现一次。如果原始列表中有重复,我们可以申请arr.unique
在串联步骤之前的每个列表。
此外,该过程可以扩展以查找两个以上集合的交集。只需将所有列表连接在一起,然后更改filter
一步从== 2
to == n
(where n
是组数)。 (注:使用is_duplicated
上面的表达式不适用于两个以上的集合。)
The arr.eval
方法确实有一个parallel
关键词。您可以尝试将其设置为True
并看看它是否会在您的特定情况下产生更好的性能。
其他集合操作
对称差:改变filter
标准为== 1
(并省略arr.unique
step.)
联盟:使用arr.concat
其次是arr.unique
.
集合差异:计算交集(如上所述),然后连接原始列表/集合并过滤仅出现的项目once。或者,对于较小的列表大小,您可以将“a”连接到自身,然后连接到“b”,然后过滤出现两次(但不是三次)的元素。