polars-python-api中的不变性和写时复制原则



嗨,我正在进行一个名为";迷你极";。

我理解pypolars API,例如DataFrame在一般情况下引发免疫-行为或isch与"写上复制"行为相同。大多数更改DataFrame对象的方法都会返回一个廉价的副本。我知道DataFrame.extend和@columns.setter是例外。在R中,大多数API致力于严格免疫行为。我想既支持严格不可变的行为,也支持可选的类似pypolars的行为。Rust-pars API有许多可变的操作+生存期等等,但可以理解的是,这一切都与性能和表现力有关。

  • 在pypolars-API中是否存在更多的中心可变行为
  • 只有不可变行为的pypolars-API会在性能和表现力方面受到影响吗

R库data.tableAPI有时确实偏离了免疫性。然而,所有这些可变的操作都以set_为前缀或使用集合运算符:=

  • pypolar中有没有一种明显的方法来识别操作是否是可变的

通过可变行为,我想到例如在定义变量df_mutable_copy之后执行方法.extend(),这仍然会影响值df_mutable_copy

import polars as pl
df1 = pl.DataFrame({"foo": [1, 2, 3], "bar": [4, 5, 6]})
df2 = pl.DataFrame({"foo": [10, 20, 30], "bar": [40, 50, 60]})
df_copy = df1
df_copy_old_shape = df_copy.shape
df1.extend(df2)
df_copy_new_shape = df_copy.shape
#extend was a operation with mutable behaviour df_copy was affected.
df_copy_old_shape != df_copy_new_shape 

大多数python polars API实际上是polars lazy的包装器。

(df.with_columns(..)
.join(..)
.groupby()
.select(..)

翻译为:

```python
(df.lazy().with_columns(..).collect(no_optimization=True)
.lazy().join(..).collect(no_optimization=True)
.lazy().groupby().collect(no_optimization=True)
.lazy().select(..).collect(no_optimization=True)

这意味着几乎所有表达式都在polars查询引擎上运行。查询引擎本身决定操作是否可以就地完成,或者是否应该克隆数据(写入时复制(。

Polars实际上在类固醇上有Copy on write,因为它只有在数据不共享的情况下才会复制。如果我们是唯一的拥有者,我们就会发生变异。我们可以这样做,因为Rust有一个借用检查器,所以如果我们拥有数据,并且ref计数为1,我们可以对数据进行变异。

我建议您实现您的R-polars API,类似于我们在python中所做的。然后,所有的操作都可以变得纯粹(例如,返回一个新的Series/Expr/DataFrame(,民意测验将决定何时在适当的地方进行变异。

不要担心复制数据。所有数据缓冲区都封装在Arc中,所以我们只增加一个引用计数。

最新更新