Помимо Numpy и Pandas: раскрытие потенциала малоизвестных библиотек Python
Python — один из наиболее часто используемых языков программирования в мире, предоставляющий разработчикам широкий набор библиотек.
В любом случае, когда дело доходит до манипулирования данными и научных вычислений, мы обычно думаем о таких библиотеках, как Numpy
или Pandas
.
В этой статье мы представляем 3 малоизвестные Python-библиотеки, которые могут вас заинтересовать.
1. Dask
Представление Dask
Dask — это гибкая библиотека параллельных вычислений, которая обеспечивает распределённые вычисления и параллелизм для крупномасштабной обработки данных.
Итак, почему мы должны использовать Dask? Как говорится на их сайте :
Python стал доминирующим языком как для анализа данных, так и для общего программирования. Этот рост был вызван вычислительными библиотеками, такими как NumPy, pandas и scikit-learn. Однако эти библиотеки не предназначены для масштабирования за пределами одной машины. Dask был разработан для естественного масштабирования этих библиотек и окружающей экосистемы для многоядерных машин и распределённых кластеров, когда наборы данных превышают объём памяти.
Ниже представлено одно из распространённых применений библиотеки Dask:
Dask используется в ситуациях, когда Pandas терпит неудачу из-за размера данных или скорости вычислений:
– Работа с большими наборами данных, даже если эти наборы данных не помещаются в памяти.
– Ускорение длительных вычислений за счёт использования множества ядер
– Распределённые вычисления на больших наборах данных со стандартными операциями pandas, такими как группировка, объединение и вычисления временных рядов.
Таким образом, Dask — хороший выбор, когда нам нужно иметь дело с огромными фреймами данных Pandas. Это связано с тем, что Dask позволяет пользователям управлять наборами данных объёмом более 100 ГБ на ноутбуке или наборами данных объёмом более 1 ТБ на рабочей станции, что является довольно впечатляющим результатом.
Что происходит под капотом библиотеки Dask:
Dask координирует множество Pandas DataFrames/Series, расположенных по индексу. Dask DataFrame секционируется по строкам, группируя строки по значению индекса для эффективности. Эти объекты pandas могут существовать на диске или на других аппаратах.
Итак, у нас есть что-то вроде этого:
Некоторые возможности Dask в действии
Прежде всего, нам нужно установить Dask. Мы можем сделать это через pip
или conda
вот так:
$ pip install dask[complete]
or
$ conda install dask
ОСОБЕННОСТЬ ПЕРВАЯ: ОТКРЫТИЕ CSV-ФАЙЛА
Первая особенность Dask, которую мы можем показать, — это то, как мы можем открыть CSV-файлы. Мы можем сделать это так:
import dask.dataframe as dd
# Load a large CSV file using Dask
df_dask = dd.read_csv('my_very_large_dataset.csv')
# Perform operations on the Dask DataFrame
mean_value_dask = df_dask['column_name'].mean().compute()
Итак, как мы видим в коде, то, как мы используем Dask, очень похоже на использование Pandas. В частности:
- Используем метод
read_csv()
точно так же, как в Pandas - Перехватываем столбец точно так же, как в Pandas. На самом деле, если бы у нас был фрейм данных Pandas
df
, мы бы перехватывали столбец следующим образом:df['column_name']
. - Применяем метод
mean()
к перехваченному столбцу аналогично Pandas, но здесь также нужно добавить методcompute()
.
Кроме того, даже если методология открытия CSV-файла такая же, как в Pandas, под капотом Dask без особых усилий обрабатывает большой набор данных, который превышает объём памяти одной машины.
Это означает, что мы не видим никакой реальной разницы, кроме того факта, что большой фрейм данных нельзя открыть в Pandas, а в Dask — можно.
ОСОБЕННОСТЬ ВТОРАЯ: МАСШТАБИРОВАНИЕ РАБОЧИХ ПРОЦЕССОВ МАШИННОГО ОБУЧЕНИЯ
Мы также можем использовать Dask для создания набора данных классификации с огромным количеством образцов. Затем мы можем разделить его на тренировочные и тестовые наборы, подогнать тренировочный набор к модели ML и рассчитать прогнозы для набора тестов.
Мы можем сделать это так:
import dask_ml.datasets as dask_datasets
from dask_ml.linear_model import LogisticRegression
from dask_ml.model_selection import train_test_split
# Load a classification dataset using Dask
X, y = dask_datasets.make_classification(n_samples=100000, chunks=1000)
# Split the data into train and test sets
X_train, X_test, y_train, y_test = train_test_split(X, y)
# Train a logistic regression model in parallel
model = LogisticRegression()
model.fit(X_train, y_train)
# Predict on the test set
y_pred = model.predict(X_test).compute()
В этом примере подчёркивается способность Dask обрабатывать огромные наборы данных даже в случае проблемы машинного обучения путём распределения вычислений по нескольким ядрам.
В частности, мы можем создать «Dask dataset» для случая классификации с помощью метода dask_datasets.make_classification()
, а также указать количество выборок и чанков (даже очень большое!).
Как и раньше, прогнозы создаются методом compute()
.
ПРИМЕЧАНИЕ:
в этом случае вам может понадобиться установить все модули dask_ml.
Вы можете сделать это так:
$ pip install dask_ml
ОСОБЕННОСТЬ ТРЕТЬЯ: ЭФФЕКТИВНАЯ ОБРАБОТКА ИЗОБРАЖЕНИЙ
Сила параллельной обработки, которую использует Dask, также может быть применена к изображениям.
В частности, мы могли открывать несколько изображений, изменять их размер и сохранять в изменённом размере. Мы можем сделать это так:
import dask.array as da
import dask_image.imread
from PIL import Image
# Load a collection of images using Dask
images = dask_image.imread.imread('image*.jpg')
# Resize the images in parallel
resized_images = da.stack([da.resize(image, (300, 300)) for image in images])
# Compute the result
result = resized_images.compute()
# Save the resized images
for i, image in enumerate(result):
resized_image = Image.fromarray(image)
resized_image.save(f'resized_image_{i}.jpg')
Ниже описан процесс:
- Открываем все изображения формата «.jpg» в текущей папке (или в папке, которую вы можете указать) методом
dask_image.imread.imread("image*.jpg")
. - Изменяем их все на 300×300, используя понимание списка в методе
da.stack()
. - Вычисляем результат методом
compute()
, как и раньше. - Сохраняем все изменённые изображения с помощью цикла for.
2. SymPy
Представление SymPy
Если вам нужно выполнять математические расчёты и вычисления и вы хотите придерживаться Python, вы можете попробовать библиотеку Sympy.
Действительно: зачем использовать другие инструменты и программное обеспечение, когда мы можем использовать наш любимый Python?
Согласно тому, что они пишут на своем веб-сайте:
Sympy – библиотека Python для символьной математики. Она стремится стать полнофункциональной системой компьютерной алгебры (CAS), сохраняя при этом максимально простой код, чтобы она была понятной и легко расширяемой. SymPy полностью написана на Python.
Но зачем использовать SymPy? Вот несколько аргументов:
SymPy – …
– Бесплатный: SymPy под лицензией BSD бесплатен.
– На основе Python: SymPy полностью написан на Python и использует Python в качестве своего языка.
– Лёгкий: SymPy зависит только от mpmath, чистой библиотеки Python для произвольной арифметики с плавающей точкой, что делает его простым в использовании инструментом.
– Библиотека: помимо использования в качестве интерактивного инструмента, SymPy может быть встроен в другие приложения и дополнен пользовательскими функциями.
Таким образом, SymPy в основном обладает всеми характеристиками, которые могут понравиться любителям Python!
Теперь давайте посмотрим на некоторые его особенности.
Некоторые возможности SymPy в действии
Прежде всего, нам нужно установить данную библиотеку:
$ pip install sympy
ОБРАТИТЕ ВНИМАНИЕ:
если вы напишете $ pip install simpy, вы установите другую (совершенно
другую!) библиотеку.
Итак, вторая буква “y”, а не “i”.
ОСОБЕННОСТЬ ПЕРВАЯ: РЕШЕНИЕ АЛГЕБРАИЧЕСКОГО УРАВНЕНИЯ
Если нам нужно решить алгебраическое уравнение, мы можем использовать SymPy следующим образом:
from sympy import symbols, Eq, solve
# Define the symbols
x, y = symbols('x y')
# Define the equation
equation = Eq(x**2 + y**2, 25)
# Solve the equation
solutions = solve(equation, (x, y))
# Print solution
print(solutions)
>>>
[(-sqrt(25 - y**2), y), (sqrt(25 - y**2), y)]
Итак, процесс:
- Определим символы уравнения методом
symbols()
. - Запишем алгебраическое уравнение методом
Eq
. - Решаем уравнение методом
solve()
.
Когда я учился в университете, я использовал разные инструменты для решения подобных задач, и должен сказать, что SymPy, как мы видим, очень удобочитаем и удобен для пользователя.
ОСОБЕННОСТЬ ВТОРАЯ: ВЫЧИСЛЕНИЕ ПРОИЗВОДНЫХ
Вычисление производных — ещё одна задача, которая может понадобиться нам с математической точки зрения по многим причинам при анализе данных. Часто нам могут понадобиться расчеты по какой-либо причине, и SymPy действительно упрощает этот процесс. Мы можем сделать это так:
from sympy import symbols, diff
# Define the symbol
x = symbols('x')
# Define the function
f = x**3 + 2*x**2 + 3*x + 4
# Calculate the derivative
derivative = diff(f, x)
# Print derivative
print(derivative)
>>>
3*x**2 + 4*x + 3
Итак, как мы видим, процесс очень прост и понятен:
- Мы определяем символ функции, которую мы получаем, с помощью
symbols()
. - Определяем функцию.
- Вычисляем производную с указанием функции
diff()
и символа, с которым мы вычисляем производную (это абсолютная производная, но мы могли бы вычислить даже частные производные в случае функций, которые имеют переменныеx
иy
).
Если провести тест, то мы увидим, что результат получается за 2-3 секунды.
ОСОБЕННОСТЬ ТРЕТЬЯ: РАСЧЕТ ИНТЕГРАЛА
Конечно, если SymPy может вычислять производные, он также может вычислять и интегралы. Давайте сделаем это:
from sympy import symbols, integrate, sin
# Define the symbol
x = symbols('x')
# Perform symbolic integration
integral = integrate(sin(x), x)
# Print integral
print(integral)
>>>
-cos(x)
Здесь мы используем метод integrate()
, указав функцию для интегрирования и переменную интегрирования.
3. Xarray
Представление Xarray
Xarray — это библиотека Python, которая расширяет функциональные возможности NumPy, давая нам возможность работать с помеченными массивами и наборами данных.
Как говорится на их сайте:
Xarray делает работу с помеченными многомерными массивами в Python простой, эффективной и увлекательной!
А также :
Xarray вводит метки в виде размеров, координат и атрибутов поверх необработанных многомерных массивов, подобных NumPy, что обеспечивает более интуитивно понятный, более лаконичный и менее подверженный ошибкам опыт разработчиков.
Другими словами, он расширяет функциональность массивов NumPy, добавляя метки или координаты к размерам массива. Эти метки предоставляют метаданные и обеспечивают более продвинутый анализ и обработку многомерных данных.
Например, в NumPy доступ к массивам осуществляется с помощью индексации на основе целых чисел.
А в Xarray каждое измерение может иметь связанную с ним метку, что упрощает понимание данных и управление ими на основе осмысленных имен.
Например, вместо доступа к данным с помощью arr[0, 1, 2]
, мы можем использовать arr.sel(x=0, y=1, z=2)
в Xarray, где x
, y
и z
— метки измерений.
Это делает код более читабельным!
Итак, давайте посмотрим на некоторые особенности Xarray.
Некоторые возможности Xarray в действии
Как обычно, код для установки данной библиотеки:
$ pip install xarray
ОСОБЕННОСТЬ ПЕРВАЯ: РАБОТА С ПОМЕЧЕННЫМИ КООРДИНАТАМИ
Предположим, мы хотим создать некоторые данные, связанные с температурой, и мы хотим пометить их координатами, такими как широта и долгота. Мы можем сделать это так:
import xarray as xr
import numpy as np
# Create temperature data
temperature = np.random.rand(100, 100) * 20 + 10
# Create coordinate arrays for latitude and longitude
latitudes = np.linspace(-90, 90, 100)
longitudes = np.linspace(-180, 180, 100)
# Create an Xarray data array with labeled coordinates
da = xr.DataArray(
temperature,
dims=['latitude', 'longitude'],
coords={'latitude': latitudes, 'longitude': longitudes}
)
# Access data using labeled coordinates
subset = da.sel(latitude=slice(-45, 45), longitude=slice(-90, 0))
И если мы выведем их, то получим:
# Print data
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
Итак, рассмотрим процесс пошагово:
- Мы создали значения температуры в виде массива NumPy.
- Мы определили значения широты и долготы как массивы NumPy.
- Мы сохранили все данные в массиве Xarray с помощью метода
DataArray()
. - Мы выбрали подмножество широт и долгот с помощью метода
sel()
, который выбирает значения, которые мы хотим для нашего подмножества.
Результат легко читается, поэтому маркировка действительно полезна во многих случаях.
ОСОБЕННОСТЬ ВТОРАЯ: ОБРАБОТКА ОТСУТСТВУЮЩИХ ДАННЫХ
Предположим, мы собираем данные о температуре в течение года. Мы хотим знать, есть ли в нашем массиве нулевые значения. Вот как мы можем это сделать:
import xarray as xr
import numpy as np
import pandas as pd
# Create temperature data with missing values
temperature = np.random.rand(365, 50, 50) * 20 + 10
temperature[0:10, :, :] = np.nan # Set the first 10 days as missing values
# Create time, latitude, and longitude coordinate arrays
times = pd.date_range('2023-01-01', periods=365, freq='D')
latitudes = np.linspace(-90, 90, 50)
longitudes = np.linspace(-180, 180, 50)
# Create an Xarray data array with missing values
da = xr.DataArray(
temperature,
dims=['time', 'latitude', 'longitude'],
coords={'time': times, 'latitude': latitudes, 'longitude': longitudes}
)
# Count the number of missing values along the time dimension
missing_count = da.isnull().sum(dim='time')
# Print missing values
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 к Xarray, например isnull.sum()
, как в этом случае, который подсчитывает общее количество пропущенных значений.
ОСОБЕННОСТЬ ТРЕТЬЯ: ОБРАБОТКА И АНАЛИЗ МНОГОМЕРНЫХ ДАННЫХ
Соблазн обрабатывать и анализировать многомерные данные высок, когда у нас есть возможность маркировать наши массивы. Так почему бы не попробовать?
Например, предположим, что мы всё ещё собираем данные о температуре на определённых широтах и долготах.
Мы можем захотеть рассчитать среднюю, максимальную и медианную температуры. Мы можем сделать это так:
import xarray as xr
import numpy as np
import pandas as pd
# Create synthetic temperature data
temperature = np.random.rand(365, 50, 50) * 20 + 10
# Create time, latitude, and longitude coordinate arrays
times = pd.date_range('2023-01-01', periods=365, freq='D')
latitudes = np.linspace(-90, 90, 50)
longitudes = np.linspace(-180, 180, 50)
# Create an Xarray dataset
ds = xr.Dataset(
{
'temperature': (['time', 'latitude', 'longitude'], temperature),
},
coords={
'time': times,
'latitude': latitudes,
'longitude': longitudes,
}
)
# Perform statistical analysis on the temperature data
mean_temperature = ds['temperature'].mean(dim='time')
max_temperature = ds['temperature'].max(dim='time')
min_temperature = ds['temperature'].min(dim='time')
# Print values
print(f"mean temperature:\n {mean_temperature}\n")
print(f"max temperature:\n {max_temperature}\n")
print(f"min temperature:\n {min_temperature}\n")
>>>
mean temperature:
<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
max temperature:
<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
min temperature:
<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,
10.04924046, 10.00645499]])
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
И мы получили то, что хотели, ещё и в чётко читаемом виде.
И снова, как и раньше, для вычисления максимального, минимального и среднего значений температуры мы использовали функции Pandas, применённые к массиву.
Выводы
В этой статье мы показали три Python-библиотеки для научных расчётов и вычислений.
В то время как SymPy может заменить другие инструменты и программное обеспечение, давая нам возможность использовать код Python для математических вычислений, Dask и Xarray расширяют функциональные возможности других библиотек, помогая нам в ситуациях, когда у нас могут возникнуть трудности с другими наиболее известными библиотеками Python для анализа и обработки данных.