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()
)   

Polars简明基础教程系列

Polars简明基础教程一:Polars快速入门

Polars简明基础教程二:懒惰模式 1:引入懒惰模式

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

Polars简明基础教程四:懒惰模式 2:评估查询

  • 5
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
polars是一个基于Rust语言的数据处理库,它提供了类似于pandas的数据操作功能。下面是polars使用教程的简要介绍: 1. 安装polars: 首先,你需要在你的项目中添加polars作为依赖项。可以通过在Cargo.toml文件中添加以下行来实现: ``` [dependencies] polars = "0.16" ``` 2. 导入polars: 在你的Rust代码中,使用`use`关键字导入polars库: ```rust use polars::prelude::*; ``` 3. 创建DataFrame: 使用`DataFrame`结构来表示数据集。你可以从不同的数据源创建DataFrame,例如CSV文件、内存中的数据等。以下是从CSV文件创建DataFrame的示例: ```rust let df = CsvReader::from_path("data.csv") .unwrap() .infer_schema(None) .unwrap() .has_header(true) .finish() .unwrap(); ``` 4. 数据操作: polars提供了丰富的数据操作功能,包括选择列、过滤行、排序、聚合等。以下是一些常见的数据操作示例: - 选择列: ```rust let selected_df = df.select(&["column1", "column2"]); ``` - 过滤行: ```rust let filtered_df = df.filter(col("column1").gt(lit(10))); ``` - 排序: ```rust let sorted_df = df.sort("column1", false); ``` - 聚合: ```rust let aggregated_df = df.groupby("column1").agg(&[col("column2").sum(), col("column3").mean()]); ``` 5. 数据输出: polars支持将DataFrame导出为不同的数据格式,例如CSV、Parquet等。以下是将DataFrame导出为CSV文件的示例: ```rust df.write_csv("output.csv").unwrap(); ``` 这只是polars的一小部分功能介绍,你可以查阅polars的官方文档以获取更详细的信息。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值