您的位置:首页 > 健康 > 美食 > Polars简明基础教程三:懒惰模式 1:引入懒惰模式(续)

Polars简明基础教程三:懒惰模式 1:引入懒惰模式(续)

2024/10/30 9:06:50 来源:https://blog.csdn.net/sosogod/article/details/141046722  浏览:    关键词:Polars简明基础教程三:懒惰模式 1:引入懒惰模式(续)

懒惰模式 1

在DataFrame和LazyFrame上的操作

为了展示在DataFrame和LazyFrame上操作的差异,我们使用rename方法将PassengerID列重命名为Id。

在DataFrame上,我们会看到第一列已经被重命名...

(df_eager.rename({"PassengerId":"Id"}).head(2)
)    

而在LazyFrame上,我们会看到查询计划中增加了一个RENAME步骤。

(df_lazy.rename({"PassengerId":"Id"})
)    

链式调用或重新赋值?

在这门课程中,我们通常像这样使用链式调用来执行操作

(pl.scan_csv(csv_file).rename({"PassengerId":"Id"})
)    

然而,我们也可以在每一步中通过重新赋值给变量来执行操作

df_lazy = pl.scan_csv(csv_file)
df_lazy = df_lazy.rename({"PassengerId":"Id"})

当使用DataFrames或LazyFrames时,这两种方法是等效的。

查询优化

Polars 从您的查询中创建一个“简单查询计划”。这意味着这个查询计划没有经过优化。

Polars 将简单查询计划传递给其查询优化器。查询优化器会寻找更高效的方法来获得您想要的输出。

explain 方法展示了优化后的计划。我们使用 print 语句来正确地格式化它。

print(pl.scan_csv(csv_file).explain()
)

在这个简单的例子中,查询计划显示我们:

  1. 扫描CSV文件
  2. 选择所有12列(*/12*)

输出是一个 DataFrame。

应用了哪些查询优化?

查询优化并不是魔法。如果用户知道优化的存在、记得实现优化并且正确地实现了优化,大多数优化都可以通过用户在精心编写的查询中实现。

Polars应用的优化包括:

  • projection pushdown:限制读取的列数至所需列
  • predicate pushdown:尽早应用过滤条件
  • combine predicates:合并多个过滤条件
  • slice pushdown:当需要限制行数时,限制处理的行数
  • common subplan elimination:对相同的数据只运行一次重复的转换,然后重用
  • common subexpression elimination:重复的表达式被缓存并重用

我们在课程的后续部分会看到这些优化中的大部分是如何产生的。

公共子表达式消除

在这里,我们会看到公共子表达式消除优化是如何工作的。通过公共子表达式消除,Polars识别出哪些相同的表达式被计算了多次,因此Polars会缓存第一次的输出以便重用。

在这个例子中,我们有一个延迟查询,其中我们扫描了Titanic CSV文件。然后,我们:

  1. 使用select来输出一列或多列的子集
  2. 创建一个第一个表达式,它包含平均年龄减去一个标准差
  3. 创建一个第二个表达式,它包含平均年龄
  4. 创建一个第三个表达式,它包含平均年龄加上一个标准差
  5. 使用.collect来评估查询
(pl.scan_csv(csv_file).select((pl.col("Age").mean() - pl.col("Age").std()).alias("minus_one_std"),pl.col("Age").mean().alias("mean"),(pl.col("Age").mean() + pl.col("Age").std()).alias("plus_one_std"),).collect()
)       

在这个查询中,我们重复使用了pl.col("Age").mean()和pl.col("Age").std()这两个表达式。如果我们使用.explain打印优化后的查询计划,可以看到Polars正在应用公共子表达式优化。

print(pl.scan_csv(csv_file).select((pl.col("Age").mean() - pl.col("Age").std()).alias("minus_one_std"),pl.col("Age").mean().alias("mean"),(pl.col("Age").mean() + pl.col("Age").std()).alias("minus_one_std"),).explain()
)               

这个查询计划由FROM分隔为两个块。

在上面的SELECT块中,我们看到这些表达式是以__POLARS_CSER_X的形式调用的,其中均值表达式有一个代码,标准差表达式也有一个代码。我们可以看到,Polars已经识别出这些是在SELECT块中的三个表达式中相同的子表达式。

Polars还实现了其他优化,例如在排序数据上的快速路径算法(与查询优化器分开)。我们将在课程的后续部分中进一步了解这些优化。

练习

在练习中,你将增强对以下内容的理解:

  1. 从CSV文件创建LazyFrame
  2. 从LazyFrame获取元数据
  3. 打印查询计划

练习 1

通过扫描Titanic CSV文件来创建一个LazyFrame

df = pl.<blank>

检查你可以从LazyFrame中获取以下哪些元数据:

  • 行数
  • 列名
  • 模式(schema)

创建一个懒加载查询,其中扫描Titanic CSV文件,然后选择Name和Age列。

(pl.scan_csv(csv_file)<blank>
)

打印出这个查询的优化后查询计划

解决方案

练习1的解决方案

通过扫描Titanic CSV文件来创建一个LazyFrame

df = pl.scan_csv(csv_file)

LazyFrame不知道CSV中的行数

df.shape

LazyFrame知道列名。正如我们将在I/O部分看到的那样,Polars通过pl.scan_csv扫描CSV文件的第一行来获取列名。

df.schema

创建一个延迟查询,其中扫描Titanic CSV文件,然后选择Name和Age列。

(pl.scan_csv(csv_file).select("Name","Age")
)   

打印这个查询的优化后的查询计划

print(pl.scan_csv(csv_file).select("Name","Age").explain()
)   

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com