在极坐标中使用数据框名称和 pl.col() 选择列之间的区别

Aks*_*hay 3 dataframe python-polars

我对 Polar 还比较陌生。我对其运作有一些疑问。我可以在 Polars 中执行这样的操作,

df = df.with_columns(((pl.col("netsales")/pl.col("sold_quantity")).alias("net_div"))
Run Code Online (Sandbox Code Playgroud)

同样可以使用以下方法实现,

df = df.with_columns((df["netsales"]/df["sold_quantity"]).alias("net_div"))
Run Code Online (Sandbox Code Playgroud)

就性能而言,它们之间有什么区别吗?

还,

df = df.with_columns((df["netsales"]/df["sold_quantity"]).alias("net_mul"),
(df["netsales"]+df["sold_quantity"]).alias("net_add")
)
Run Code Online (Sandbox Code Playgroud)

上述操作可以像这样单独完成,

df = df.with_columns((df["netsales"]/df["sold_quantity"]).alias("net_mul"))
df = df.with_columns((df["netsales"]+df["sold_quantity"]).alias("net_add"))
Run Code Online (Sandbox Code Playgroud)

上述两种方式执行相同的操作在性能上有什么区别吗?我在网上找不到与此相关的任何答案或文档。如果您能分享一些这方面的知识,我将感谢您的支持。

Dea*_*gor 5

让我们从这个开始:

df = df.with_columns((df["netsales"]/df["sold_quantity"]).alias("net_div"))
Run Code Online (Sandbox Code Playgroud)

退后一步,当你打电话时会发生什么df["netsales"]

它将该列提取为与该列同名的系列。当您将一个系列除以另一个系列时,它会产生另一个具有每个元素商的系列,正如您所期望的那样。

with_columns当您喂食系列时会发生什么?它要么添加一列,要么用该数据替换现有列(假设它们具有相同的高度)。

由于Python的操作顺序,Python将在Polars知道你在做什么之前解决系列除法,所以没有办法插入一个警告,告诉你不应该这样做。

你为什么不应该这样做呢?

性能实验

设置
import polars as pl
import numpy as np
df=pl.DataFrame({
    'a':np.random.normal(5,2,int(10e7)),
    'b':np.random.normal(5,2,int(10e7)),
    'c':np.random.normal(5,2,int(10e7)),
    'd':np.random.normal(5,2,int(10e7)),
    'e':np.random.normal(5,2,int(10e7))
    })
Run Code Online (Sandbox Code Playgroud)
使用方括号符号进行测试
df.with_columns(df[x]**2.3 for x in df.columns)
# takes 7.9s and only uses one core
Run Code Online (Sandbox Code Playgroud)
用表达式进行测试
df.with_columns(pl.col(x)**2.3 for x in df.columns)
# takes 2.2s and uses 5 cores, corresponding to 5 columns
Run Code Online (Sandbox Code Playgroud)

默认情况下,Polars 会自动并行运行所有表达式。当您使用方括号表示法时,您就不允许这种情况发生。你不允许这种情况发生的原因是 python 将在将生成器交给它之前解析生成器中的所有元素,with_columns并且由于 python 本质上是串行的,这就是你得到的。

人体工学

在表达式的情况下,你可以这样做

df.with_columns(pl.all()**2.3)
Run Code Online (Sandbox Code Playgroud)

还有一整套列选择器可以微调选择列。

with_columns此外,使用表达式可以让您将多个、等链接在一起filter,并且表达式根据上下文执行

例如你不能这样做

(
    df
    .filter(pl.col('netsales')<1000)
    .with_columns(
        df["netsales"]/df["sold_quantity"]
        )
    )
Run Code Online (Sandbox Code Playgroud)

因为df["netsales"]不知道过滤器,所以尺寸会错误。

通过表达式,你可以做到

(
    df
    .filter(pl.col('netsales')<1000)
    .with_columns(pl.col("netsales")/pl.col("sold_quantity"))
    )
Run Code Online (Sandbox Code Playgroud)

惰性框架

对于 LazyFrames,数据尚未制成表格,因此您不能使用方括号表示法。