数据分析神器Python Polars快速入门1简介(下:行列操作、方法链及处理大于RAM的数据集)

1.6 选择列和过滤数据
我们将具体介绍列选择和过滤。

选择和过滤是评估 Polars 表达式的两种主要情况。当我们在这些上下文中使用表达式时,Polars 的功能就会大放异彩。

您将学习如何使用一些最常用的 DataFrame 方法:.select()、.with_columns() 和 .filter()。

准备

import polars as pl
df = pl.read_csv(r’d:\code\titanic_dataset.csv’)
df.head()
使用 .select() 方法选择列。只需在方法中指定一个或多个列名即可。或者,也可以使用 pl.col() 方法用表达式选择列:

使用 .with_columns() 选择列:

以下代码也实现类似效果:

df.with_columns(
pl.col(‘Survived’),
pl.col(‘Ticket’),
pl.col(‘Fare’)
).head()
使用 .filter() 过滤数据:

我们使用多重条件过滤数据:

.select() 和 .with_columns() 方法都用于列的选择和操作。请注意,.select() 和 .with_columns() 方法的输出不同,尽管在前面的示例中语法非常相似。

.select() 和 .with_columns() 方法的区别在于,.select() 会删除未选择的列,而 .with_columns() 则会替换同名的现有列。如果只在 .with_columns() 中指定现有列,基本上就等于选择了所有列。

.filter() 方法只是根据您用表达式编写的条件过滤数据。您需要使用 & 或 | 来表示 and 和 or 运算符。

在 Polars 中,您可以像在 pandas 中一样选择列:

你可以做某事并不意味着你应该做某事。最好的做法是尽可能使用表达式。表达式可以帮助你充分发挥 Polars 的潜力,包括使用并行执行和查询优化。

当你开始使用表达式时,通过使用方法链,你的代码将变得更加简洁易读。

本节值得介绍几种更先进、更方便的选择列的方法。

其中之一就是通过正则表达式(regex)选择列。本例选择字符长度小于或等于 4 的列:

顺便提一下,使用 regex 时,以下网站非常有用:https://regexr.com。

另一种选择列的方法是使用数据类型。让我们选择数据类型为字符串的列:

选择列的更高级方法是使用选择器命名空间中的函数。下面是一个简单的示例:

下面是如何使用 cs.matches() 函数,选择包含单词 “se ”或 “ed ”的列:

您还可以使用选择器进行更多操作,例如设置操作(如联合或相交)。有关可用选择器功能的更多信息,请参阅 Polars 文档:https://pola-rs.github.io/polars/py-polars/html/reference/selectors.html。

1.6.1 参考

https://pola-rs.github.io/polars/user-guide/expressions/column-selections
https://pola-rs.github.io/polars/py-polars/html/reference/dataframe/api/polars.DataFrame.filter.html
参考资料
软件测试精品书籍文档下载持续更新 https://github.com/china-testing/python-testing-examples 请点赞,谢谢!
本文涉及的python测试开发库 谢谢点赞! https://github.com/china-testing/python_cn_resouce
python精品书籍下载 https://github.com/china-testing/python_cn_resouce/blob/main/python_good_books.md
Linux精品书籍下载 https://www.cnblogs.com/testing-/p/17438558.html
1.7 创建、修改和删除列
本节将介绍的主要方法有 .select()、.with_columns() 和 .drop()。

根据另一列创建一列:

我们添加了名为 max_fare 的新列。它的值是票价列的最大值。

您可以不使用 .alias() 为列命名。您需要在表达式的开头指定名称。请注意,这种方法不能在列名中使用空格:

如果不指定新列名,则基础列将被覆盖:

为了演示如何对一列使用多个表达式,让我们为这一列添加另一个逻辑:

我们添加了一列,可以计算票价列的最大值和平均值,并进行减法运算。这只是如何使用 Polars 表达式的一个示例。

使用 pl.lit() 方法创建带字面意义值的列:

使用 .with_row_index() 添加行计数:

修改列中的值

我们将 Sex 列转换为标题大小写。.str 使你可以访问 Polars 中的字符串方法,我们将在第 6 章 “执行字符串操作 ”中介绍这些方法。

删除列:

使用 .select() 来选择要保留的列:

只要您想指定一个字面或常量值,就可以使用 pl.lit() 方法。您不仅可以使用字符串值,还可以使用整数、布尔、列表等各种数据类型。

创建或添加新列时,有三种方法可以为其命名:

使用 .alias()。在表达式开头定义列名,如前面的例子:max_fare=pl.col(‘Fare’).max()。列名中不能使用空格。

请勿指定列名,因为如果新列是基于另一列创建的,那么列名将取代现有列名。或者,在使用 pl.lit() 时,该列将以字面形式命名。

.select()和.with_columns()方法都可以创建和修改列。区别在于是保留未指定的列还是删除它们。基本上,在添加新列的同时,可以使用 .select() 方法放弃列。这样,当仅使用 .select() 方法就能完成工作时,就可以避免同时使用 .with_columns() 和 .drop() 方法。

此外,请注意在使用 .select() 或 .with_columns() 方法时,新增或修改的列不会持久存在。如果需要,您需要将结果存储到变量中:

df = df.with_columns(
pl.col(‘Fare’).max()
)
最佳做法是尽可能将所有表达式放在一个方法中,而不是使用多个 .with_columns()。这样可以确保表达式并行执行,而如果使用多个 .with_columns(),Polars 引擎可能无法识别它们是否并行运行。

您应该这样编写代码

best_practice = (
df.with_columns(
pl.col(‘Fare’).max().alias(‘Max Fare’)、
pl.lit(‘Titanic’)、
pl.col(‘Sex’).str.to_titlecase()
)
)
避免这样编写代码:

not_so_good_practice = (
df
.with_columns(pl.col(‘Fare’).max().alias(‘Max Fare’))
.with_columns(pl.lit(‘Titanic’))
.with_columns(pl.col(‘Sex’).str.to_titlecase())
)
上述两个查询都会产生以下输出结果:

您无法在同一方法(如 .with_columns() 方法)中定义的另一个新列之上添加新列。只有当新列依赖于数据集中尚未存在的另一新列时,才需要使用多个方法。

1.7.1 参考

https://pola-rs.github.io/polars/user-guide/concepts/expressions/
https://www.pola.rs/posts/the-expressions-api-in-polars-is-amazing/
https://pola-rs.github.io/polars/user-guide/concepts/contexts/
https://pola-rs.github.io/polars/py-polars/html/reference/expressions/api/polars.lit.html
https://pola-rs.github.io/polars/py-polars/html/reference/expressions/api/polars.Expr.alias.html
1.8 方法链
方法链是一种结构化代码的技术或方法。它常用于 DataFrame 库,如 pandas 和 PySpark。顾名思义,它是指将方法一个接一个地链起来。这使得代码更可读、更简洁、更易维护。它遵循从一个操作到另一个操作的自然流程,从而使您的代码易于遵循。所有这些都有助于您专注于数据转换逻辑和您要解决的问题。

Polars 非常适合方法链。Polars 使用的表达式和其他方法可以很容易地堆叠在一起。

推荐使用这种方式:

df = (
df
.select(cols)
.filter(pl.col(‘Age’)>=35)
.sort(by=[‘Age’, ‘Name’])
)
需要注意的是,如果代码链过长,可能会导致代码难以阅读和处理。长链带来的复杂性增加也会使调试变得困难。要理解长链中的每一个中间步骤可能会变得非常困难。在这种情况下,您应该将逻辑分解成更小的片段,以帮助降低复杂性和减少链的长度。说了这么多,归根结底,要使代码测试可行,就必须取得平衡。

为了充分披露信息,请记住您没有义务使用方法链。如果你觉得逐行单独编写代码更舒适或更合适,那也没有关系。方法链只是另一种做法,很多人都觉得它很有帮助。我可以自信地说,方法链对我来说利大于弊。

1.8.1 参考

https://ponder.io/professional-pandas-the-pandas-assign-method-and-chaining/
https://tomaugspurger.net/posts/method-chaining/
1.9 处理大于 RAM 的数据集
Polars 的突出特点之一是它的流模式。它是 lazy API 的一部分,允许您处理大于机器可用内存的数据。使用流模式,您可以让机器分批处理庞大的数据。否则,你将无法处理如此庞大的数据。

需要注意的一点是,流模式并不支持所有的懒操作,因为它仍在开发中。您仍然可以在查询中使用任何懒操作,但最终,Polars 引擎将决定该操作是否可以在流模式下执行。如果答案是否定的,那么 Polars 将使用非流式模式运行查询。我们可以预见,随着时间的推移,这一功能将包括更多的懒惰操作,并变得更加复杂。

我们将通过创建一个简单的查询来演示流模式如何工作,该查询用于读取一个大于机器可用 RAM 的 .csv 文件,并使用流模式进行处理。

我使用的是一个出租车出行数据集,磁盘容量超过 80 GB。您可以从以下网站下载该数据集:https://data.cityofchicago.org/Transportation/Taxi-Trips-2013-2023-/wrvz-psew/about_data 。

taxi_trips = (
pl.scan_csv(‘~/Downloads/Taxi_Trips.csv’)
.collect(streaming=True)
)
taxi_trips.head()

使用 .scan_read() 代替 .read_csv()。在 .collect() 中指定了一个参数。它变成了.collect(streaming=True)。
我们将通过在 .collect() 方法中设置 streaming=True 来启用流模式。在这个具体例子中,我只读取一个 .csv 文件,并不复杂。我使用 .scan_read() 方法以懒惰模式读取。

理论上,如果没有流模式,我就无法处理这个数据集。这是因为我的笔记本电脑有 64 GB 内存(是的,我的笔记本电脑有相当大的内存!),低于磁盘上超过 80 GB 的数据集大小。

我的笔记本电脑在流模式下处理数据大约花了两分钟。如果不使用流模式,我就会出现内存不足的错误。你可以在 .collect() 方法中不使用 streaming=True 的情况下运行代码来确认这一点。

如果您正在进行读取数据以外的其他操作,如聚合和过滤,那么 Polars(使用 LazyFrame)可能会优化您的查询,使其无需在内存中读取整个数据集。这意味着您甚至不需要使用流模式来处理大于内存的数据。聚合和过滤本质上是汇总数据或减少行数,从而无需读取整个数据集。

假设你对一列进行了简单的分组和聚合,就像下面代码中的那样。你会发现,不使用流模式也能运行它(这取决于你选择的数据集和机器的可用内存):

trip_total_by_pay_type = (
pl.scan_csv(‘~/Downloads/Taxi_Trips.csv’)
.group_by(‘Payment Type’)
.agg(pl.col(‘Trip Total’).sum())
.collect()
)
trip_total_by_pay_type.head()
上述代码将返回以下输出结果:

尽管如此,当数据集的大小可能超过可用 RAM 或数据大小可能随时间增长时,使用 streaming=True 仍然是个好主意。

参考:https://pola-rs.github.io/polars-book/user-guide/concepts/streaming/ 。

声明:文中观点不代表本站立场。本文传送门:https://eyangzhen.com/421278.html

(0)
联系我们
联系我们
分享本页
返回顶部