超越Pandas:大数据集的7种高级数据操作技术
介绍
如果你在Python中处理过数据,那么你很可能已经多次使用过Pandas。而且这是有充分理由的;它直观、灵活,并且非常适合日常分析。但是,当你的数据集开始增长时,Pandas也开始显示出它的局限性。也许是内存问题,缓慢的性能,或者当你尝试按几百万行进行分组时,你的机器发出的声音像要起飞一样。
这是许多数据分析师和科学家开始问相同问题的转折点:除此之外还有什么?
本文讨论的是如何回答这个问题。我们将探讨七个工具和技术,这些工具和技术超越了Pandas,适用于更大的数据、更快的执行和更高效的管道。到文章结束时,你将知道何时换挡、使用什么工具以及如何在自己的工作流程中实际使用它。
1. 使用 Dask 对DataFrame进行并行化
Pandas框架非常棒,直到你的数据集无法放入内存。一旦遇到这个问题,事情很快就会变得混乱。这就是Dask出现的地方。
Dask旨在让Pandas用户感到熟悉,但在幕后,它将您的数据分割成块并并行处理。它不会试图一次加载所有内容。相反,它根据需求处理数据的一部分,甚至可以将计算分布在多个核心或机器上。您无需重写整个工作流程即可获得巨大的性能提升。
Dask真正的魔力来自于三件事:
- 惰性求值:Dask 不会立即运行操作。它会构建任务图,并在需要时执行,这意味着减少了更多的计算浪费。
- 离线计算:您可以处理比 RAM 大的数据集,通过从磁盘流式传输数据。
- 并行执行:过滤、连接和分组等操作可以在多个CPU核心上运行,而无需您额外的努力。
这是一个简单的例子,展示了如何加载一个大的CSV文件并执行分组操作,就像在Pandas中一样:
注意.compute()
在末尾;那就是 Dask 实际上触发计算的地方。在此之前,它只是在构建需要执行的步骤。
2. 加速使用极坐标
如果Dask帮助你扩展并行性,Polars帮助你提高速度。它不仅仅是为了快而快;它的速度让你感觉像是作弊。
Polars 是一个用 Rust 编写的 DataFrame 库,它依赖于 Apache Arrow 内存格式来获得惊人的速度提升。这意味着当你运行一个查询时,它会编译一个计划,在多个线程上运行,并在 Pandas 甚至完成解析你的 CSV 文件之前交付结果。
但这里是什么让它脱颖而出:Polars 不仅仅关乎速度。它还关乎管道思维。你不是写逐行脚本;而是构建一个只有在需要时才会执行的转换链。
让我们来看一个使用 Polars 的懒惰 API 的例子。我们将读取一个大文件,过滤它,并运行一个groupby
聚合操作,而无需一次将所有内容加载到内存中:
注意 collect()
在最后?那就是一切运行的时刻。在此之前,你只是在制定计划。由于 Polars 编译了该计划,它运行得紧凑而整洁,没有 Python 拓展,也没有逐行迭代。
Polars在你需要单台机器上的最高速度时表现得非常出色。想想仪表板、分析管道,或者在将大量数据输入模型之前清理这些数据。如果你在使用Pandas时遇到性能瓶颈,并且不想启动集群或处理并行引擎,这就是你的捷径。
同样值得注意的是:语法简洁。一旦你习惯用表达式思考,它比编写循环和连贯的Pandas调用感觉更敏锐。
3. 与Apache Arrow合作
有时候速度不是关于更快地进行计算。有时候,它是指在不需要的时候不移动数据。这正是Apache Arrow发挥作用的地方。
Arrow 并不是一个你会直接互动的工具,比如 Pandas 或 Polars;它更像是隐藏在下面的管道。但是,一旦你理解了它的功能,你就会开始看到它如何融入许多现代工作流程。
本质上,Arrow 是一种列式内存格式。这意味着它按列(而不是按行)存储数据,并且采用的设计布局是为了速度,不仅在一个工具内部,而且在工具之间也是如此。因此,当 Pandas、Polars、PySpark 或甚至是数据库引擎使用 Arrow 时,它们可以在彼此之间传递数据而无需复制或转换。没有序列化,也没有等待。
让我们来实际操作一下。假设你有一个Pandas DataFrame,并希望将其转换为Polars以获得更快的groupby
,或者导出它以便其他服务可以使用而无需重新处理。
这可能如下所示:
4. 使用SQL引擎(例如DuckDB,SQLite)查询
有时,处理大数据最快的方法不是Pandas、Polars或Spark,而是古老的SQL。这不仅仅是在说话怀旧。SQL仍然是运行分析查询最有效的方法之一,特别是当你只需要过滤、分组或连接大型数据集时,而不需要启动整个处理管道。
DuckDB 类似于 SQLite,但针对分析工作负载进行了优化。它可以查询 Parquet 文件、CSV 或 Arrow 表,而无需将它们加载到内存中的 DataFrame 中。它完全在你的机器上运行,没有服务器,没有集群,没有设置。只需安装软件包并编写 SQL。
这是一个例子。假设你有一个大的Parquet文件,并且想要通过日期筛选找到每类的平均销售额:
不需要先用Pandas加载文件;DuckDB负责解析、过滤、分组,并且速度很快。它还很聪明地将过滤条件下推到文件级别(尤其是Parquet文件),所以它不会浪费时间扫描不需要的数据。
如果你在一个使用SQL作为共同语言的团队中工作,这是一个很好的方法来本地原型设计然后再扩展到一个完整的数据库。
使用 DuckDB 的情况:
- 您的数据对于Pandas来说太大了,但您还没有准备好使用Spark。
- 你想直接从磁盘查询数据(CSV、Parquet、Arrow)
- 您需要快速、可重复、基于SQL的分析,而无需设置基础设施
5. 使用 PySpark 进行分布式处理
在某个时刻,你的数据集变得如此之大,以至于它不仅仅会减慢你的机器,还会损坏它。到那时,是时候拿出 PySpark了。
PySpark 通过 Python 接口为您提供 Apache Spark 的功能。它为分布式计算而设计,这意味着它可以跨多个核心或机器处理数据,而您无需管理底层的细节。如果您正在处理 数据湖、数十亿行数据或生产级管道,这是您需要的工具。
Spark 给你两种主要的工作方式:RDDs(容错分布式数据集)和 DataFrames。除非你有非常具体的原因要使用低级 API,否则请使用 DataFrames。它们经过优化,更容易编写,并且如果你使用过 Pandas 或 SQL,会更加熟悉。
让我们逐步了解一个基本的PySpark流程,读取一个大的CSV文件,进行过滤和聚合:
这看起来很像Pandas,但执行方式完全不同。操作是惰性评估的,并且在运行之前会在幕后进行优化(或者即使是在本地,如果你只是在测试)。
使用 PySpark 的情况:
- 您的数据无法放在单台机器上
- 您正在分布式环境中工作(例如云平台或本地集群)
- 你需要将容错、重试逻辑和可扩展性内置到你的工作流程中。
需要注意的一点:对于小型任务,PySpark 并不是总是最快的选项。当规模和韧性比方便或启动时间更重要时,它才表现出色。
6. 用Vaex进行优化
如果你曾经尝试将一个巨大的CSV加载到Pandas中,然后看到你的内存瞬间消失,你并不孤单。大多数DataFrame工具试图将所有内容都保留在内存中,当你处理超过一亿行的数据时,这根本无法扩展。
Vaex 是一个专为高性能、单机分析而构建的DataFrame库。它速度快、内存高效,并且为懒惰而设计,但不是以一种坏的方式,而是以在你需要的时候才加载它的方式。
使Vaex与众不同的地方是它使用了内存映射文件。它不是将整个数据集加载到内存中,而是按需直接从磁盘读取块。结合其优化的后端(用C++编写),即使在处理巨大的数据集时,也能实现过滤、聚合和连接等超快操作。
以下是实际操作的示例:
就是这样;不需要.compute()
调用。Vaex在幕后计算出最佳执行路径,并仅在必要时运行它。它还缓存结果并尽量减少不必要的重新计算。
你应该在什么情况下选择 Vaex?
- 您正在处理大数据集(数千万或数亿行),但又不想使用Dask或Spark的开销
- 你想要超快的,分析风格的查询:过滤器、分箱、直方图、连接
- 你需要一个高效的东西,可以在 单台机器上运行而不会吃掉你所有的RAM
7. 基于生成器的分块和流式处理
有时候,最明智的行动是降低到低级层次。当你的机器在处理一个文件时卡住了,而所有的工具都显得过于沉重时,Python 的内置工具仍然可以拯救这一天。在内存极其紧张的情况下——也许你正在处理一个嵌入设备,运行在 lambda 函数内部,或者只是试图避免将数百兆字节加载到 RAM 中——你并不总是需要一个 DataFrame。
生成器和文件迭代器 让你可以逐行流式处理数据。你不会加载文件;你会在运行中处理它。这意味着内存使用量始终保持稳定,没有峰值,并且可以完全控制接下来会发生什么。
这是一个简单的例子:逐行读取大型CSV文件,过滤行,并在过程中进行一些简单的转换:
没有Pandas。没有库。只有完全控制的干净迭代。你什么时候应该走这条路?
- 您正在内存紧张的环境中操作,例如云函数或边缘计算
- 你需要逐行流式传输数据,可能传输到另一个系统(如数据库、API 或文件)
- 您希望在不使用大型框架的情况下构建自己的轻量级ETL管道
总结
这概述的要点不是挑选一个赢家。而是挑选适合工作的工具。
如果你想在最少的更改下扩展你的Pandas代码,Dask 是一个坚实的第一步。对于单台机器上的纯粹速度,Polars 是令人震惊的快。如果你关心互操作性或在系统之间传递数据,Arrow 保持事物紧凑和高效。更喜欢SQL?DuckDB 让你可以在不设置数据库的情况下对大文件运行分析查询。
处理大规模数据集或企业管道?那是PySpark的领域。需要在笔记本电脑上快速进行分析吗?Vaex给你映射内存的性能和Pandas的感觉。当只需要保持简单和紧凑时,Python自己的生成器可以逐行流式处理数据而不会有任何压力。
有时将工具结合在一起是“最佳”方法:使用 Arrow 和 Polars,或者将文件加载到 DuckDB 中并导出为 Arrow 以在管道的另一步中使用。你不必局限于一个生态系统。你也不需要完全放弃 Pandas。
单和紧凑时,Python自己的生成器可以逐行流式处理数据而不会有任何压力。
有时将工具结合在一起是“最佳”方法:使用 Arrow 和 Polars,或者将文件加载到 DuckDB 中并导出为 Arrow 以在管道的另一步中使用。你不必局限于一个生态系统。你也不需要完全放弃 Pandas。
重要的是了解你的选项,并构建一个与你的数据相配合而不是与之对抗的堆栈。