折叠
Polars
提供了横向表达式或者方法,比如sum
,
min
, mean
等等,
我们只需要设置 axis=1
即可实现横向聚合。但是,当我们需要复杂的聚合模式时,Polars
提供的基本函数可能不能胜任,这时候我们需要 fold
函数。
fold
函数在列方向的性能最佳,它很好的利用了数据的内存格局,通常还会伴随向量化操作。
让我们通过里一个例子看看如何受使用 fold
实现 sum
函数。
手工 sum
{
"a": [1, 2, 3],
"b": [10, 20, 30],
}
)
out = df.select(
pl.fold(acc=pl.lit(0), function=lambda acc, x: acc + x, exprs=pl.col("*")).alias("sum"),
)
print(out)
shape: (3, 1)
┌─────┐
│ sum │
│ --- │
│ i64 │
╞═════╡
│ 11 │
│ 22 │
│ 33 │
└─────┘
上面的例子中,函数 f(acc, x) -> acc
被反复调用并把结果累加到 acc
变量,最终把结果放入 x 列。
这个函数按照列执行,并且充分利用了缓存和向量化操作。
条件语句
当我们希望对一个 DataFrame
的所有列是施加条件语句的时候,采用 fold
就非常简洁。
{
"a": [1, 2, 3],
"b": [0, 1, 2],
}
)
out = df.filter(
pl.fold(
acc=pl.lit(True),
function=lambda acc, x: acc & x,
exprs=pl.col("*") > 1,
)
)
print(out)
shape: (1, 2)
┌─────┬─────┐
│ a ┆ b │
│ --- ┆ --- │
│ i64 ┆ i64 │
╞═════╪═════╡
│ 3 ┆ 2 │
└─────┴─────┘
上面的例子中,我们选择所有行,这些行的每一列都大于 1。
fold
和 字符串数据
Fold 可以用来连接字符串。但是由于这个操作会产生一些中间结果,这个操作是 O(n^2)
的时间复杂度。
因此,我们推荐使用 concat_str
表达式。
df = pl.DataFrame(
{
"a": ["a", "b", "c"],
"b": [1, 2, 3],
}
)
out = df.select(
[
pl.concat_str(["a", "b"]),
]
)
print(out)
shape: (3, 1)
┌─────┐
│ a │
│ --- │
│ str │
╞═════╡
│ a1 │
│ b2 │
│ c3 │
└─────┘