应用-在 Pandas 中读取 CSV 的最快方法

目录

在 Pandas 中读取 CSV 的最快方法

你有一个大型 CSV 文件,准备将其读入 Pandas——但每次加载时,你都必须等待 CSV 加载完成。这会减慢你的开发反馈循环,并可能显著减慢你的生产处理速度。

但我们可以通过更快地读取数据来加速这一过程。让我们来看看如何实现。

在本文中,我们将介绍:

  1. Pandas 默认的 CSV 读取方式。
  2. 在 v1.4 中引入的更快、更并行的 CSV 读取器。
  3. 一种可以使速度更快的不同方法。

默认方式读取 CSV

我手头有一个 850MB 的 CSV 文件,里面是本地公交系统的延误数据。以下是使用 Pandas 默认方式加载它的代码:

import pandas as pd

df = pd.read_csv("large.csv")

通过使用 time 工具运行我们的程序,以下是所需的时间:

$ time python default.py 

real    0m13.245s
user    0m11.808s
sys     0m1.378s

基本上“real”是墙上时钟的经过时间,其他两个指标是 CPU 时间,分为在应用程序代码中运行的时间(“user”)和在 Linux 内核中运行的时间(“sys”)。

Pandas 的 CSV 读取器有多个后端;这是用 C 编写的 "c" 后端。如果我们使用 "python" 后端,它会运行得更慢,但我不会展示这一点,因为它确实很慢。

使用 PyArrow 读取 CSV

在 2022 年 1 月发布的 Pandas 1.4 中,有一个新的 CSV 读取后端,依赖于 Arrow 库的 CSV 解析器。它仍然标记为实验性,并且不支持默认解析器的所有功能——但它更快。

以下是我们的使用方式:

import pandas as pd

df = pd.read_csv("large.csv", engine="pyarrow")

当我们运行它时:

$ time python arrow.py 

real    0m2.707s
user    0m4.945s
sys     0m1.527s

让我们比较两种实现:

CSV 解析器经过时间CPU 时间(user+sys)
默认 C 后端13.2 秒13.2 秒
PyArrow 后端2.7 秒6.5 秒

首先关注 CPU 时间,PyArrow 实现使用的 CPU 时间减少了一半。这是一个很好的改进。

其次,经过时间更快,实际上经过时间比 CPU 时间低得多。这是因为它使用了并行性——与默认后端不同,它利用了我的计算机的多核特性。

现在,并行性可能是一个好处,也可能不是,这取决于你如何运行代码。如果你之前只在单核上运行它,那么这是一个免费的性能提升。但如果你已经手动利用了多核,例如通过并行加载多个 CSV 文件,那么在这里添加并行性不会加快速度,甚至可能会稍微减慢速度。

然而,鉴于 PyArrow 后端本身更快,因为总 CPU 时间减少了一半,即使你已经有了并行性,它也可能提供有意义的速度提升。

重新思考问题

加载 CSV 本质上是一项繁重的工作:

  1. 你需要将文件拆分为行。
  2. 你需要将每行按逗号拆分。
  3. 你需要处理字符串引用。
  4. 你需要猜测列的类型,除非你显式地将它们传递给 Pandas。
  5. 你需要将字符串转换为整数、日期和其他非字符串类型。

所有这些都需要 CPU 时间。

如果你从第三方获取 CSV 文件,并且只处理一次,那么你对此无能为力。但如果你多次加载相同的 CSV 文件呢?或者,如果你在数据处理管道的其他部分生成了输入文件呢?

你可以读取其他文件格式,而不是 CSV,这样可以更快地处理数据。 让我们看一个使用 Parquet 数据格式的示例。Parquet 文件设计为快速读取:你不必像处理 CSV 那样进行那么多解析。而且与 CSV 不同,CSV 中的列类型没有编码在文件中,而在 Parquet 中,列的类型存储在文件中。

首先,我们将 CSV 文件转换为 Parquet 文件;我们禁用压缩,以便与 CSV 进行更公平的比较。当然,如果你是生成文件的人,你不需要转换步骤,可以直接将数据写入 Parquet。

import pandas as pd

df = pd.read_csv("large.csv")
df.to_parquet("large.parquet", compression=None)

我们运行一次:

$ time python convert.py

real    0m18.403s
user    0m15.695s
sys     0m2.107s

我们可以读取 Parquet 文件;在我的计算机上,fastparquet 引擎似乎是两个选项中较快的,但你也可以尝试 pyarrow 后端。

import pandas as pd

df = pd.read_parquet("large.parquet", engine="fastparquet")

如果我们运行它:

$ time python parquet.py 

real    0m2.441s
user    0m1.990s
sys     0m0.575s

进行比较:

解析器经过时间CPU 时间(user+sys)
默认 CSV13.2 秒13.2 秒
PyArrow CSV2.7 秒6.5 秒
fastparquet2.4 秒2.6 秒

仅从 CPU 时间来看,fastparquet 是最快的。它是否能提供经过时间的改进取决于你是否已经有并行性、你的计算机等因素。不同的 CSV 文件可能会有不同的解析成本;这只是一个示例。但显然读取 Parquet 格式要高效得多。

最好的 CSV 是没有 CSV

CSV 是一种糟糕的格式。除了解析效率低下之外,缺乏类型数据意味着解析总是比具有实际列类型的结构化文件格式更容易出错和模糊。因此,如果可以,请避免使用 CSV,并使用更好的格式,例如 Parquet。

如果你不得不使用 CSV,请考虑使用 Pandas 1.4 中的新 PyArrow CSV 解析器;你会获得不错的速度提升,尤其是如果你的程序当前没有利用多核 CPU。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

李星星BruceL

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值