我有一个像这样的数据框:
data = {
"a": [[1], [2], [3, 4], [5, 6, 7]],
"b": [[], [8], [9, 10], [11, 12]],
}
df = pl.DataFrame(data)
"""
┌───────────┬───────────┐
│ a ┆ b │
│ --- ┆ --- │
│ list[i64] ┆ list[i64] │
╞═══════════╪═══════════╡
│ [1] ┆ [] │
│ [2] ┆ [8] │
│ [3, 4] ┆ [9, 10] │
│ [5, 6, 7] ┆ [11, 12] │
└───────────┴───────────┘
"""
每对列表的长度可能不一样,我想将爆炸“截断”为两个列表中最短的一个:
"""
┌─────┬─────┐
│ a ┆ b │
│ --- ┆ --- │
│ i64 ┆ i64 │
╞═════╪═════╡
│ 2 ┆ 8 │
│ 3 ┆ 9 │
│ 4 ┆ 10 │
│ 5 ┆ 11 │
│ 6 ┆ 12 │
└─────┴─────┘
"""
我在想,也许我必须用 填充两个列表中最短的列表以None
匹配两个长度,然后drop_nulls
。但我想知道是否有更直接的方法可以解决这个问题?
1
最佳答案
2
以下是一种方法:
min_length = pl.min_horizontal(pl.col('a', 'b').list.len())
out = (df.filter(min_length != 0)
.with_columns(
pl.col('a', 'b').list.head(min_length)
)
.explode('a', 'b')
)
输出:
shape: (5, 2)
┌─────┬─────┐
│ a ┆ b │
│ --- ┆ --- │
│ i64 ┆ i64 │
╞═════╪═════╡
│ 2 ┆ 8 │
│ 3 ┆ 9 │
│ 4 ┆ 10 │
│ 5 ┆ 11 │
│ 6 ┆ 12 │
└─────┴─────┘
解释
- 使用 获取两列列表的长度,并使用 获取每行的最短列表。
min_length == 0
现在,过滤出( )中的行,并用 选择每个列表的前 n 个值。- 最后,应用。
2
-
为什么需要过滤器?
– -
@Hericks:第一行有一个空列表(
[]
),因此如果没有过滤器,就会导致出现一行[ null, null ]
,而这是OP不想要的。
–
|
我无法将其挤在评论中,因此我只能在这里提供另一个答案,因为对于给定的示例来说它更为通用:
(
df.with_columns(
(x := pl.all().list).head(
pl.min_horizontal(x.len())
)
).explode("*")
.drop_nulls()
)
shape: (5, 2)
┌─────┬─────┐
│ a ┆ b │
│ --- ┆ --- │
│ i64 ┆ i64 │
╞═════╪═════╡
│ 2 ┆ 8 │
│ 3 ┆ 9 │
│ 4 ┆ 10 │
│ 5 ┆ 11 │
│ 6 ┆ 12 │
└─────┴─────┘
|
[3, 4]
更改为[None, 4]
?框架中还有其他非列表列吗?–
|