问题场景

当遇到特别大的csv文件,例如500M,pandas读取会很慢,在之前教程中要使用其他包另类的语法。现在只需更新pandas,加一个参数即可。

在本文中,我们将介绍:

  • Pandas 的默认 CSV读数据, v1.4 中引入的更快、更并行的 CSV解析器。
  • 一种不同的方法可以使事情变得更快。
  • 读取 CSV,默认方式

碰巧有一个 850MB 的 CSV 文件,这是使用 Pandas 加载它的默认方式:

## 更新pandas
!pip3 install --upgrade pandas
import pandas as pd

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

下面是旧的pandas版本代码读数据所消耗时间

0m13.245s


使用pyarrow读csv

2022年1月份,刚刚发布的pandas1.4版本增加了arrow库的csv解析器。对了,该功能仍然处于试验阶段,不是默认解析器,但是足够快。下面是新版本用法

import pandas as pd

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

新版本代码读数据所消耗时间

0m6.507s

CSV解析器 CPU运行时间
默认C 13.2s
PyArrow 6.5s

需要注意,如果你的数据分析项目已经使用了并行加速数据的读取,那么今天的新教程(pyarrow)并不会特别显著改善代码运行速度(十几倍加速),但至少可能提供有意义的加速(一倍左右)。


重新思考

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

  • 需要分成几行。
  • 需要用逗号分隔每一行。
  • 需要处理字符串引用。
  • 需要猜测(!)列的类型,除非您明确地将它们传递给 Pandas。
  • 需要将字符串转换为整数、日期和其他非字符串类型。

所有这些都需要 CPU 时间。

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

您可以读取其他一些处理速度更快的文件格式,而不是读取 CSV。让我们看一个例子,使用 Parquet 数据格式。 Parquet 文件旨在快速读取:您不必像使用 CSV 那样进行大量解析。与 CSV 不同,其中列类型在文件读取时无需编码,在 Parquet 中,列的类型存储在实际文件中。

首先,我们将 CSV 文件转换为 Parquet 文件;我们禁用压缩,因此我们正在与 CSV 进行更多的苹果对苹果的比较。当然,如果您是第一个生成文件的人,则不需要转换步骤,您可以直接将数据写入 Parquet。

import pandas as pd

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

现在我们的数据存在于large.parquet中,再读取large.parquet看看读取时间

import pandas as pd

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

2.441s

CSV解析器 CPU运行时间
默认C 13.2s
PyArrow 6.5s
fastparquet 2.4s

纯粹由 CPU 衡量,fastparquet 是迄今为止最快的。 这只是一个例子。 但显然阅读 Parquet 格式的效率要高得多。


最好的文件格式不是 CSV

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

如果你被 CSV 卡住了,考虑在 Pandas 1.4 中使用新的 PyArrow CSV 解析器; 你会得到很好的加速,特别是如果你的程序当前没有利用多个 CPU。



广而告之