超越Numpy和Pandas:发掘较少知名的Python库的潜力

'Exploring the potential of lesser-known Python libraries beyond Numpy and Pandas.'

作为数据专业人员,你应该了解的3个Python科学计算库

Image by OrMaVaredo on Pixabay

Python是世界上使用最广泛的编程语言之一,为开发者提供了广泛的库。

不管怎样,当涉及到数据操作和科学计算时,我们通常会考虑到像NumpyPandasSciPy这样的库。

在本文中,我们介绍了3个你可能感兴趣的Python库。

1. Dask

介绍Dask

Dask是一个灵活的并行计算库,可以实现大规模数据处理的分布式计算和并行计算。

那么,为什么我们要使用Dask呢?正如他们在他们的网站上所说:

Python已经成为数据分析和通用编程领域的主导语言。这一增长得益于像NumPy、pandas和scikit-learn这样的计算库。然而,这些包的设计并不适用于超过单台计算机的规模。当数据集超过内存时,Dask的开发目标是本地扩展这些包及其周边生态系统到多核机器和分布式集群。

所以,正如他们所说,Dask的一个常见用途是:

Dask DataFrame用于通常需要pandas的情况,通常是在pandas由于数据大小或计算速度而失败的情况下:

– 操作大型数据集,即使这些数据集不适合内存

– 通过使用多个核心加速长时间计算

– 在大型数据集上进行分布式计算,使用标准的pandas操作,如groupby、join和时间序列计算

因此,当我们需要处理巨大的Pandas数据帧时,Dask是一个不错的选择。这是因为Dask:

允许用户在笔记本电脑上操作100GB+的数据集,或者在工作站上操作1TB+的数据集

这是一个相当令人印象深刻的结果。

底层发生的情况是:

Dask DataFrame协调许多按索引排列的pandas DataFrame/Series。为了提高效率,Dask DataFrame通过索引值对行进行分组,这些pandas对象可以存储在磁盘上或其他机器上。

所以,我们有类似这样的情况:

The difference between a Dask and a Pandas data frame. Image by Author, freely inspired by one on the Dask website already quoted.

Dask的一些功能

首先,我们需要安装Dask。我们可以通过pipconda这样做:

$ pip install dask[complete]或$ conda install dask

特性一:打开CSV文件

我们可以通过以下方式打开CSV来展示Dask的第一个特性:

import dask.dataframe as dd# 使用Dask加载一个大型CSV文件df_dask = dd.read_csv('my_very_large_dataset.csv')# 在Dask DataFrame上进行操作mean_value_dask = df_dask['column_name'].mean().compute()

所以,正如我们在代码中看到的,我们使用Dask的方式与Pandas非常相似。特别是:

  • 我们像在Pandas中一样使用read_csv()方法
  • 我们像在Pandas中一样截取一个列,实际上,如果我们有一个名为df的Pandas数据帧,我们会这样截取一个列:df['column_name']
  • 我们对截取的列应用mean()方法,与Pandas类似,但这里我们还需要添加compute()方法。

此外,即使打开CSV文件的方法与Pandas相同,但在Dask的支持下,可以轻松处理超过单台机器内存容量的大型数据集。

这意味着我们几乎看不到任何实际差异,除了无法在Pandas中打开大型数据框,但在Dask中可以打开。

特性二:扩展机器学习工作流程

我们可以使用Dask创建一个包含大量样本的分类数据集。然后将其分割为训练集和测试集,对训练集进行ML模型拟合,并对测试集进行预测。

可以像这样操作:

import dask_ml.datasets as dask_datasetsfrom dask_ml.linear_model import LogisticRegressionfrom dask_ml.model_selection import train_test_split# 使用Dask加载分类数据集X, y = dask_datasets.make_classification(n_samples=100000, chunks=1000)# 将数据分割为训练集和测试集X_train, X_test, y_train, y_test = train_test_split(X, y)# 并行训练逻辑回归模型model = LogisticRegression()model.fit(X_train, y_train)# 对测试集进行预测y_pred = model.predict(X_test).compute()

该示例强调了Dask在处理巨大数据集时的能力,即使在机器学习问题中也是如此,通过将计算分布到多个核心中。

特别是,可以使用方法dask_datasets.make_classification()为分类案例创建“Dask数据集”,并且可以指定样本数和块数(甚至非常大!)。

与之前类似,预测结果可以使用compute()方法获得。

注意:在此情况下,您可能需要安装dask_ml模块。可以使用以下命令安装:$ pip install dask_ml

特性三:高效的图像处理

Dask利用的并行处理能力也可以应用于图像处理。

特别是,我们可以打开多个图像,调整尺寸并保存调整后的图像。可以像这样操作:

import dask.array as daimport dask_image.imreadfrom PIL import Image# 使用Dask加载图像集images = dask_image.imread.imread('image*.jpg')# 并行调整图像尺寸resized_images = da.stack([da.resize(image, (300, 300)) for image in images])# 计算结果result = resized_images.compute()# 保存调整后的图像for i, image in enumerate(result):    resized_image = Image.fromarray(image)    resized_image.save(f'resized_image_{i}.jpg')

所以,这是整个过程:

  1. 使用dask_image.imread.imread("image*.jpg")方法打开当前文件夹(或指定文件夹)中的所有“.jpg”图像。
  2. 使用da.stack()方法和列表推导将所有图像调整为300×300的尺寸。
  3. 使用compute()方法计算结果,和之前一样。
  4. 使用for循环保存所有调整后的图像。

2. SymPy

Introducing Sympy

如果您需要进行数学计算和计算,并希望使用Python,可以尝试使用SymPy。

的确:为什么要使用其他工具和软件,当我们可以使用我们钟爱的Python呢?

根据他们在网站上写的,SymPy是:

一个用于符号数学的Python库。它旨在成为一个全功能的计算机代数系统(CAS),同时保持代码尽可能简单,以便易于理解和扩展。SymPy完全用Python编写。

但为什么要使用SymPy?他们提到:

SymPy是…

– 自由的:在BSD许可下,SymPy既是免费的,也是开放的。

– 基于Python:SymPy完全用Python编写,并使用Python作为其语言。

– 轻量级:SymPy仅依赖于mpmath,这是一个用于任意浮点运算的纯Python库,使其易于使用。

– 一个库:除了作为交互式工具使用外,SymPy可以嵌入其他应用程序,并且可以通过自定义函数进行扩展。

所以,它基本上具有所有可能被Python爱好者喜欢的特点!

现在,让我们来看一下它的一些特点。

SymPy的一些特点

首先,我们需要安装它:

$ pip install sympy

注意:如果你写成 $ pip install simpy,你将安装另一个(完全不同的!)库。所以,第二个字母是“y”,不是“i”。

特点一:求解代数方程

如果我们需要求解一个代数方程,我们可以像这样使用SymPy:

from sympy import symbols, Eq, solve# 定义符号x, y = symbols('x y')# 定义方程equation = Eq(x**2 + y**2, 25)# 求解方程solutions = solve(equation, (x, y))# 打印解print(solutions)>>>[(-sqrt(25 - y**2), y), (sqrt(25 - y**2), y)]

所以,这是整个过程:

  1. 我们使用symbols()方法定义方程的符号。
  2. 我们使用Eq方法写出代数方程。
  3. 我们使用solve()方法求解方程。

当我在大学时,我使用了不同的工具来解决这些问题,我必须说SymPy非常易读和用户友好。

但是,确实:它是一个Python库,所以怎么会有什么不同呢?

特点二:计算导数

计算导数是我们在分析数据时可能需要的另一个任务。通常情况下,我们可能需要进行各种计算,而SymPy真的简化了这个过程。事实上,我们可以这样做:

from sympy import symbols, diff# 定义符号x = symbols('x')# 定义函数f = x**3 + 2*x**2 + 3*x + 4# 计算导数derivative = diff(f, x)# 打印导数print(derivative)>>>3*x**2 + 4*x + 3

所以,正如我们所见,这个过程非常简单和易于理解:

  1. 我们使用symbols()方法定义要求导的函数的符号。
  2. 我们定义函数。
  3. 我们使用diff()方法计算导数,指定函数和要计算导数的符号(这是绝对导数,但在具有xy变量的函数的情况下,我们甚至可以执行偏导数)。

如果我们进行测试,我们会看到结果在2或3秒内到达。所以,它也非常快速。

特点三:计算积分

当然,如果SymPy可以计算导数,它也可以计算积分。让我们来做一下:

from sympy import symbols, integrate, sin# 定义符号x = symbols('x')# 进行符号积分integral = integrate(sin(x), x)# 打印积分print(integral)>>>-cos(x)

所以,这里我们使用integrate()方法,指定要积分的函数和积分变量。

这难道不是更简单吗?!

3. Xarray

介绍Xarray

Xarray是一个扩展了NumPy功能的Python库,它使我们能够使用带有标签的数组和数据集。

正如他们在他们的网站上所说的:

Xarray使在Python中使用带有标签的多维数组变得简单、高效和有趣!

还有:

Xarray在原始类似于NumPy的多维数组之上引入了维度、坐标和属性等标签,这使得开发者的体验更直观、更简洁,更不容易出错。

换句话说,它通过为数组维度添加标签或坐标来扩展NumPy数组的功能。这些标签提供元数据并使多维数据的高级分析和操作更容易。

例如,使用NumPy,可以使用基于整数的索引访问数组。

而在Xarray中,每个维度可以与一个标签关联,这样可以更容易地基于有意义的名称理解和操作数据。

例如,我们可以使用arr.sel(x=0, y=1, z=2)来访问数据,而不是使用arr[0, 1, 2],其中xyz是维度标签。

这使得代码更易读!

那么,让我们来看看Xarray的一些特点。

Xarray的一些特点

像往常一样,安装它:

$ pip install xarray

特点一:使用标记的坐标

假设我们想创建一些与温度相关的数据,并且我们想使用纬度和经度等坐标对其进行标记。我们可以这样做:

import xarray as xr
import numpy as np

# 创建温度数据
temperature = np.random.rand(100, 100) * 20 + 10

# 创建纬度和经度的坐标数组
latitudes = np.linspace(-90, 90, 100)
longitudes = np.linspace(-180, 180, 100)

# 使用标记的坐标创建一个Xarray数据数组
da = xr.DataArray(
    temperature,
    dims=['latitude', 'longitude'],
    coords={'latitude': latitudes, 'longitude': longitudes}
)

# 使用标记的坐标访问数据
subset = da.sel(latitude=slice(-45, 45), longitude=slice(-90, 0))

如果我们打印它们,我们会得到:

# 打印数据
print(subset)
>>>
<xarray.DataArray (latitude: 50, longitude: 25)>
array([[13.45064786, 29.15218061, 14.77363206, ..., 12.00262833, 16.42712411, 15.61353963],
       [23.47498117, 20.25554247, 14.44056286, ..., 19.04096482, 15.60398491, 24.69535367],
       [25.48971105, 20.64944534, 21.2263141 , ..., 25.80933737, 16.72629302, 29.48307134],
       ...,
       [10.19615833, 17.106716  , 10.79594252, ..., 29.6897709 , 20.68549602, 29.4015482 ],
       [26.54253304, 14.21939699, 11.085207  , ..., 15.56702191, 19.64285595, 18.03809074],
       [26.50676351, 15.21217526, 23.63645069, ..., 17.22512125, 13.96942377, 13.93766583]])
Coordinates:
  * latitude   (latitude) float64 -44.55 -42.73 -40.91 ... 40.91 42.73 44.55
  * longitude  (longitude) float64 -89.09 -85.45 -81.82 ... -9.091 -5.455 -1.818

所以,让我们逐步看一下这个过程:

  1. 我们创建了温度值作为一个NumPy数组。
  2. 我们定义了纬度和经度值作为NumPy数组。
  3. 我们使用DataArray()方法将所有数据存储在一个Xarray数组中。
  4. 我们使用sel()方法选择我们想要的子集的纬度和经度的值。

结果也很容易读取,所以标记在很多情况下确实很有帮助。

特点二:处理缺失数据

假设我们正在收集与一年中的温度相关的数据。我们想知道我们的数组中是否有一些空值。以下是我们可以这样做的方法:

import xarray as xrimport numpy as npimport pandas as pd# 创建包含缺失值的温度数据temperature = np.random.rand(365, 50, 50) * 20 + 10temperature[0:10, :, :] = np.nan  # 将前10天设置为缺失值# 创建时间、纬度和经度坐标数组times = pd.date_range('2023-01-01', periods=365, freq='D')latitudes = np.linspace(-90, 90, 50)longitudes = np.linspace(-180, 180, 50)# 创建一个带有缺失值的Xarray数据数组da = xr.DataArray(    temperature,    dims=['time', 'latitude', 'longitude'],    coords={'time': times, 'latitude': latitudes, 'longitude': longitudes})# 沿时间维度计算缺失值的数量missing_count = da.isnull().sum(dim='time')# 打印缺失值print(missing_count)>>><xarray.DataArray (latitude: 50, longitude: 50)>array([[10, 10, 10, ..., 10, 10, 10],       [10, 10, 10, ..., 10, 10, 10],       [10, 10, 10, ..., 10, 10, 10],       ...,       [10, 10, 10, ..., 10, 10, 10],       [10, 10, 10, ..., 10, 10, 10],       [10, 10, 10, ..., 10, 10, 10]])Coordinates:  * latitude   (latitude) float64 -90.0 -86.33 -82.65 ... 82.65 86.33 90.0  * longitude  (longitude) float64 -180.0 -172.7 -165.3 ... 165.3 172.7 180.0

因此,我们得到有10个空值。

此外,如果我们仔细查看代码,我们可以看到我们可以将Pandas的方法应用于像isnull().sum()这样的Xarray,以计算缺失值的总数。

特性一:处理和分析多维数据

当我们有可能对数组进行标记时,处理和分析多维数据是非常诱人的。那么,为什么不试一试呢?

例如,假设我们仍在收集与特定纬度和经度相关的温度数据。

我们可能想计算平均温度、最高温度和中位数温度。我们可以这样做:

import xarray as xrimport numpy as npimport pandas as pd# 创建合成温度数据temperature = np.random.rand(365, 50, 50) * 20 + 10# 创建时间、纬度和经度坐标数组times = pd.date_range('2023-01-01', periods=365, freq='D')latitudes = np.linspace(-90, 90, 50)longitudes = np.linspace(-180, 180, 50)# 创建一个带有温度数据的Xarray数据集ds = xr.Dataset(    {        'temperature': (['time', 'latitude', 'longitude'], temperature),    },    coords={        'time': times,        'latitude': latitudes,        'longitude': longitudes,    })# 对温度数据执行统计分析mean_temperature = ds['temperature'].mean(dim='time')max_temperature = ds['temperature'].max(dim='time')min_temperature = ds['temperature'].min(dim='time')# 打印结果print(f"平均温度:\n {mean_temperature}\n")print(f"最高温度:\n {max_temperature}\n")print(f"最低温度:\n {min_temperature}\n")>>>平均温度:<xarray.DataArray 'temperature' (latitude: 50, longitude: 50)>array([[19.99931701, 20.36395016, 20.04110699, ..., 19.98811842,        20.08895803, 19.86064693],       [19.84016491, 19.87077812, 20.27445405, ..., 19.8071972 ,        19.62665953, 19.58231185],       [19.63911165, 19.62051976, 19.61247548, ..., 19.85043831,        20.13086891, 19.80267099],       ...,       [20.18590514, 20.05931149, 20.17133483, ..., 20.52858247,        19.83882433, 20.66808513],       [19.56455575, 19.90091128, 20.32566232, ..., 19.88689221,        19.78811145, 19.91205212],       [19.82268297, 20.14242279, 19.60842148, ..., 19.68290006,        20.00327294, 19.68955107]])Coordinates:  * latitude   (latitude) float64 -90.0 -86.33 -82.65 ... 82.65 86.33 90.0  * longitude  (longitude) float64 -180.0 -172.7 -165.3 ... 165.3 172.7 180.0最高温度:<xarray.DataArray 'temperature' (latitude: 50, longitude: 50)>array([[29.98465531, 29.97609171, 29.96821276, ..., 29.86639343,        29.95069558, 29.98807808],       [29.91802049, 29.92870312, 29.87625447, ..., 29.92519055,        29.9964299 , 29.99792388],       [29.96647016, 29.7934891 , 29.89731136, ..., 29.99174546,        29.97267052, 29.96058079],       ...,       [29.91699117, 29.98920555, 29.83798369, ..., 29.90271746,        29.93747041, 29.97244906],       [29.99171911, 29.99051943, 29.92706773, ..., 29.90578739,        29.99433847, 29.94506567],       [29.99438621, 29.98798699, 29.97664488, ..., 29.98669576,        29.91296382, 29.93100249]])Coordinates:  * latitude   (latitude) float64 -90.0 -86.33 -82.65 ... 82.65 86.33 90.0  * longitude  (longitude) float64 -180.0 -172.7 -165.3 ... 165.3 172.7 180.0最低温度:<xarray.DataArray 'temperature' (latitude: 50, longitude: 50)>array([[10.0326431 , 10.07666029, 10.02795524, ..., 10.17215336,        10.00264909, 10.05387097],       [10.00355858, 10.00610942, 10.02567816, ..., 10.29100316,        10.00861792, 10.16955806],       [10.01636216, 10.02856619, 10.00389027, ..., 10.0929342 ,        10.01504103, 10.06219179],       ...,       [10.00477003, 10.0303088 , 10.04494723, ..., 10.05720692,        10.122994  , 10.04947012],       [10.00422182, 10.0211205 , 10.00183528, ..., 10.03818058,        10.02632697, 10.06722953],       [10.10994581, 10.12445222, 10.03002468, ..., 10.06937041,       

我们以清晰易读的方式获得了我们想要的结果。

和之前一样,我们使用Pandas的函数对数组应用来计算温度的最大值、最小值和平均值。

结论

在本文中,我们展示了三个用于科学计算和计算的库。

虽然SymPy可以替代其他工具和软件,让我们能够使用Python代码进行数学计算,但Dask和Xarray扩展了其他库的功能,帮助我们在可能遇到其他已知Python数据分析和处理库困难的情况下使用。

免费的Python电子书:

正在学习Python数据科学,但遇到困难吗?订阅我的通讯,并获取我的免费电子书:这将为您提供正确的学习路径,通过实践经验学习Python数据科学。

喜欢这个故事吗?通过我的推荐链接成为VoAGI会员,每月只需支付5美元:我将获得一小部分佣金,而您不需要支付额外费用:

作为VoAGI会员,您会员费的一部分将支付给您阅读的作家,您将获得对每个故事的完全访问权...

federicotrotta.medium.com