提升Pandas代码执行速度的技巧

在处理大数据集时,代码可能会因为内存消耗过大或数据量增长而变得难以处理。这些问题可能导致错误、分析等待时间过长以及处理大型数据集的限制。本文将探讨不同的方法,以加快在Pandas中编写的代码的计算速度。

本文中提到的技巧将使项目代码更加成熟,并为节省大量时间。节省的计算时间可以转化为成本节约、更好的用户体验和更好的操作体验。当将机器学习(ML)或Python代码部署到云环境,如亚马逊网络服务(AWS)、谷歌云平台(GCP)或微软Azure时,这一点尤其有益。

目录

  • 使用Numba加速Pandas
  • 使用Dask加速Pandas计算
  • 为什么选择Dask?
  • Dask的并行处理
  • 使用Modin加速Pandas

使用Numba加速Pandas

Numba是一个开源的即时编译器(JIT),可以加速使用Numpy的代码。Pandas是建立在Numpy之上的。以下是如何使用Numba的方法:

  1. 安装Numba!pip install numba ==0.53.1
  2. 导入库import numbafrom numba import jit
  3. 定义任务:从0到100获取质数列表
  4. 不使用Numba的代码示例

以下是不使用Numba的代码示例:

def check_prime(y): prime_numbers = [] for num in y: flag = False if num > 1: for i in range(2, num): if (num % i) == 0: flag = True break if flag == False: prime_numbers.append(num) return prime_numbers

计算执行时间:

import numpy as np import time x = np.arange(100) start = time.time() check_prime(x) end = time.time() print("Elapsed (with compilation) = %s" % (end - start))

使用Numba的JIT装饰器进行编码:

@jit(nopython=True) def check_prime(y): prime_numbers = [] for num in y: flag = False if num > 1: for i in range(2, num): if (num % i) == 0: flag = True break if flag == False: prime_numbers.append(num) return np.array(prime_numbers)

计算执行时间:

start = time.time() check_prime(x) end = time.time() print("Elapsed (with compilation) = %s" % (end - start))

在Jupyter笔记本中,%timeit魔法函数是最佳选择,因为它多次循环运行函数以获得更准确的执行时间估计。

%timeit check_prime(x)

可以看到,使用Numba进行计算的速度非常快。

使用Dask加速Pandas计算

Dask为Python中的数据分析提供了高效的并行化。Dask DataFrame允许在只需最小的代码更改的情况下,使用大型数据集进行数据操作和构建机器学习模型。它是开源的,并且与NumPy、scikit-learn等Python库兼容。

  1. 安装Dask!pip install dask==2021.05.0
  2. 安装Graphviz!pip install graphviz==0.16
  3. 安装Python-Graphviz!pip install python-graphviz

导入Dask并打印版本:

import dask print(dask.__version__)

当数据量超过RAM容量时,Pandas就不够用了。可能会使用Spark或Hadoop来解决这个问题。但是,这些不是Python环境。这阻止了使用NumPy、scikit-learn、Pandas、TensorFlow等常用的Python机器学习库。它们可以扩展到集群。这就是Dask发挥作用的地方。

任务:对两个分别价值100和200的产品应用20%的折扣,并生成总账单。

不使用Dask的函数定义:

from time import sleep def apply_discount(x): sleep(1) x = x - 0.2 * x return x def get_total_price(a, b): sleep(1) return a + b

计算总账单并记录所需时间:

%%time product1 = apply_discount(100) product2 = apply_discount(200) total_bill = get_total_price(product1, product2)

使用Dask并检查所需时间:

from dask import delayed %%time product1 = delayed(apply_discount)(100) product2 = delayed(apply_discount)(200) total_bill = delayed(get_total_price)(product1, product2) total_bill

可以看到,使用delayed包装器的总时间仅为374微秒。但工作尚未开始。delayed包装器创建了一个delayed对象,它跟踪所有要调用的函数和要传递给它的参数。基本上,它构建了一个任务图,解释了整个计算过程。还没有输出。

大多数Dask工作负载是懒惰的,即它们不开始任何工作,直到明确使用compute()触发它们。

total_bill.compute()

现在有了输出。这个操作也花费了一些时间。让计算总时间:

%%time product1 = delayed(apply_discount)(100) product2 = delayed(apply_discount)(200) total_bill = delayed(get_total_price)(product1, product2) total_bill.compute()

总时间是2.01秒。比原始函数少了1秒。Dask.delayed是如何做到的呢?

可以通过调用visualize()函数来查看Dask创建的最优任务图。

total_bill.visualize()

从上面的图像中,可以看到有两个apply_discount()函数实例并行调用。这是通过同时执行它们来节省时间和处理能力的机会。

Modin是一个Python库,可以使用并行化处理大型数据集。它使用Ray或Dask提供一种轻松加速操作的方式。语法与Pandas相似,其惊人的性能使其成为一个有前途的解决方案。只需要更改一行代码。

  1. 安装Modin依赖项和Dask!pip install -U pandas!pip install modin[dask]!pip install "dask[distributed]"

Modin还允许选择用于计算的引擎。环境变量MODIN_ENGINE用于此目的。以下代码显示了如何指定计算引擎:

import os os.environ["MODIN_ENGINE"] = "ray" # Modin将使用Ray os.environ["MODIN_ENGINE"] = "dask" # Modin将使用Dask

默认情况下,Modin将使用系统上所有可用的核心。但是,如果希望限制核心数量,以便执行其他任务,可以使用以下命令限制Modin使用的CPU数量:

import os os.environ["MODIN_CPUS"] = "4"

导入ModinPandas

import modin.pandas as pd

将使用pandas_pd表示Pandas,modin_pd表示Modin。首先,让使用Pandas加载数据。

import pandas as pandas_pd import time pandas_df = pandas_pd.read_csv("your_dataset.csv")

初始化Dask客户端:

from dask.distributed import Client client = Client()

使用Modin pd加载csv文件:

modin_df = pd.read_csv("Datasets/large_dataset.csv")

总时间是1分钟10秒。所需时间可能因系统规格而异。只为这样一个小任务节省了几秒钟。想象一下,在处理更大的数据集和大量计算时,可以节省多少时间!

%time pandas_df.fillna(0) %time modin_df.fillna(0)
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485