在处理大数据集时,代码可能会因为内存消耗过大或数据量增长而变得难以处理。这些问题可能导致错误、分析等待时间过长以及处理大型数据集的限制。本文将探讨不同的方法,以加快在Pandas中编写的代码的计算速度。
本文中提到的技巧将使项目代码更加成熟,并为节省大量时间。节省的计算时间可以转化为成本节约、更好的用户体验和更好的操作体验。当将机器学习(ML)或Python代码部署到云环境,如亚马逊网络服务(AWS)、谷歌云平台(GCP)或微软Azure时,这一点尤其有益。
Numba是一个开源的即时编译器(JIT),可以加速使用Numpy的代码。Pandas是建立在Numpy之上的。以下是如何使用Numba的方法:
安装Numba
!pip install numba ==0.53.1导入库
import numbafrom numba import jit以下是不使用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为Python中的数据分析提供了高效的并行化。Dask DataFrame允许在只需最小的代码更改的情况下,使用大型数据集进行数据操作和构建机器学习模型。它是开源的,并且与NumPy、scikit-learn等Python库兼容。
安装Dask
!pip install dask==2021.05.0安装Graphviz
!pip install graphviz==0.16安装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相似,其惊人的性能使其成为一个有前途的解决方案。只需要更改一行代码。
安装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)