Ускоряем анализ данных. В 4 раза быстрее операции Pandas с минимальным изменением кода

Одним из основных ограничений Pandas является то, что он может быть медленным при работе с большими наборами данных, особенно при выполнении сложных операций. Это может расстроить специалистов по обработке данных и аналитиков, которым в своей работе необходимо обрабатывать и анализировать большие наборы данных.

Есть несколько способов решить эту проблему. Одним из способов является использование параллельной обработки.

@bigdatai – огромное количество бесплатных датасетов и интсрументов анализа данных

Введите Pandarallel

Pandarallel — это библиотека Python с открытым исходным кодом, которая обеспечивает параллельное выполнение операций Pandas с использованием нескольких CPU, что приводит к значительному ускорению.

Он построен на основе популярной библиотеки Pandas и требует лишь нескольких изменений кода.

Достижение значительного ускорения с Pandarallel

Вы можете сами убедиться, насколько быстрее pandas apply по сравнению с parallel_apply от pandarallel. Здесь pandarallel распределил нагрузку по 4 ядрам.

Ускоряем анализ данных. В 4 раза быстрее операции Pandas с минимальным изменением кода
Источник: документация Pandarallel.
Источник: документация Pandarallel.

Более конкретно, ускорение видно из диаграммы ниже.

4х ускорение. Источник: документация Pandarallel.
4х ускорение. Источник: документация Pandarallel.

Начало работы с Pandarallel

Чтобы установить Pandarallel, вы можете использовать менеджер пакетов pip:

pip install pandarallel

Вы можете импортировать пакет в свой код Python и инициализировать его.

from pandarallel import pandarallel

# Initialize pandarallel
pandarallel.initialize()

Как только это будет сделано, вы можете использовать следующие предоставленные функции.

Ускоряем анализ данных. В 4 раза быстрее операции Pandas с минимальным изменением кода

Пример кода использования Pandarallel

Давайте сначала создадим фиктивный фрейм данных, содержащий покупки на сайте электронной коммерции. Каждая строка соответствует покупке одного продукта в каждую дату. Столбцы:

  • date
  • product_id
  • quantity
import pandas as pd
import numpy as np

# Generate a dataframe.
df = pd.DataFrame()

# Generate a column of random dates from 2019-01-01 to 2019-12-31
df['date'] = pd.date_range('2019-01-01', '2019-12-31', periods=10000)

# Seed numpy random 
np.random.seed(0)

# Generate a column of random product_id from 1 to 5
df['product_id'] = np.random.randint(1, 5, 10000)

# Generate a column of quantity bought from 1 to 100
df['quantity'] = np.random.randint(1, 100, 10000)

Вот первые пять строк.

|    | date                | product_id | quantity |
|---:|:--------------------|-----------:|---------:|
|  0 | 2019-01-01 00:00:00 |          1 |       10 |
|  1 | 2019-01-01 00:52:25 |          4 |       36 |
|  2 | 2019-01-01 01:44:50 |          2 |       79 |
|  3 | 2019-01-01 02:37:15 |          1 |       33 |
|  4 | 2019-01-01 03:29:41 |          4 |       59 |

Далее давайте воспользуемся pandarallel, чтобы ускорить наш рабочий процесс. Для этого давайте инициализируем наш pandarallel.

from pandarallel import pandarallel

# Initialize pandarallel
pandarallel.initialize()

Обратите внимание, что у вас есть несколько вариантов инициализации pandarallel.

# Initialize pandarallel with a progress bar
pandarallel.initialize(progress_bar = True)

# Set the number of workers for parallelization. 
# By default, this is the number of cores available.
pandarallel.initialize(nb_workers = 4) 

# Initialize pandarallel with all logs printed.
# By default, this is 2 (display all logs), while 0 display n ologs.
pandarallel.initialize(verbose = 2)

Используйте parallel_apply для применения функции к столбцу

Давайте извлечем месяц из столбца date. Например, январь — это 1, а февраль — это 2. Для этого мы можем использовать функцию parallel_apply.

# Group date by month using parallel_apply
df['month'] = df['date'].parallel_apply(lambda x: x.month)

|    | date                | product_id | quantity | month |
|---:|:--------------------|-----------:|---------:|------:|
|  0 | 2019-01-01 00:00:00 |          1 |       10 |     1 |
|  1 | 2019-01-01 00:52:25 |          4 |       36 |     1 |
|  2 | 2019-01-01 01:44:50 |          2 |       79 |     1 |
|  3 | 2019-01-01 02:37:15 |          1 |       33 |     1 |
|  4 | 2019-01-01 03:29:41 |          4 |       59 |     1 |

Мы также можем использовать функцию lambda в parallel_apply. Давайте назначим цену для каждого product_id. Затем мы можем рассчитать revenue для каждой транзакции.

# Assign a price to each product_id 
df['price'] = df['product_id'].parallel_apply(lambda x: 5.59 if x == 1 else 1.29 if x == 2 else 3.49 if x == 3 else 6.99)

# Get the revenue
df['revenue'] = df.parallel_apply(lambda x: x['quantity']* x['price'], axis=1)
|   | date                |product_id |quantity |month |price |revenue |
|--:|:--------------------|----------:|--------:|-----:|-----:|-------:|
| 0 | 2019-01-01 00:00:00 |         1 |      10 |    1 | 5.59 |  55.9  |
| 1 | 2019-01-01 00:52:25 |         4 |      36 |    1 | 6.99 | 251.64 |
| 2 | 2019-01-01 01:44:50 |         2 |      79 |    1 | 1.29 | 101.91 |
| 3 | 2019-01-01 02:37:15 |         1 |      33 |    1 | 5.59 | 184.47 |
| 4 | 2019-01-01 03:29:41 |         4 |      59 |    1 | 6.99 | 412.41 |

Используйте parallel_apply для применения функции к группе

Вы также можете сгруппировать по определенному столбцу перед применением parallel_apply. В приведенном ниже примере мы можем сгруппировать по определенному month и получить сумму revenue за каждый месяц.

# Get the sum of revenue for every month
monthly_revenue_df = df.groupby('month').parallel_apply(np.sum)[['revenue']]

Еще лучше, мы можем вычислить скользящую сумму, используя parallel_apply.

# Generate 3-month rolling revenue by month
monthly_revenue_df['rolling_3_mth_rev'] = monthly_revenue_df['revenue'].rolling(3, min_periods=3).parallel_apply(np.sum)
|   month |   revenue |   rolling_3_mth_rev |
|--------:|----------:|--------------------:|
|       1 |    188268 |                 nan |
|       2 |    164251 |                 nan |
|       3 |    176198 |              528717 |
|       4 |    178021 |              518470 |
|       5 |    188940 |              543159 |

Используйте parallel_applymap для применения функции ко всему фрейму данных

Если есть функция, которую можно применить ко всему фрейму данных, applymap — идеальная функция. Например, чтобы преобразовать все элементы df в строку, мы можем использовать эту функцию.

# Convert every element of df to a string
df.parallel_applymap(lambda x: str(x))

Полный код

import pandas as pd
import numpy as np
from pandarallel import pandarallel

# Generate a dataframe.
df = pd.DataFrame()

# Generate a column of random dates from 2019-01-01 to 2019-12-31
df['date'] = pd.date_range('2019-01-01', '2019-12-31', periods=10000)

# Seed numpy random 
np.random.seed(0)

# Generate a column of random product_id from 1 to 5
df['product_id'] = np.random.randint(1, 5, 10000)

# Generate a column of quantity bought from 1 to 100
df['quantity'] = np.random.randint(1, 100, 10000)

# Initialize pandarallel
pandarallel.initialize()

# Group date by month using parallel_apply
df['month'] = df['date'].parallel_apply(lambda x: x.month)

# Assign a price to each product_id 
df['price'] = df['product_id'].parallel_apply(lambda x: 5.59 if x == 1 else 1.29 if x == 2 else 3.49 if x == 3 else 6.99)

# Get the revenue
df['revenue'] = df.parallel_apply(lambda x: x['quantity']* x['price'], axis=1)

# print(df.head().to_markdown())

# Get the sum of revenue for every month
monthly_revenue_df = df.groupby('month').parallel_apply(np.sum)[['revenue']]

# Generate 3-month rolling revenue by month
monthly_revenue_df['rolling_3_mth_rev'] = monthly_revenue_df['revenue'].rolling(3, min_periods=3).parallel_apply(np.sum)

# print(monthly_revenue_df.head().to_markdown())

Когда НЕ использовать Pandarallel

Мы не должны использовать Pandarallel, когда данные не помещаются в память. В этом случае используйте sparkpyspark или vaex.

Тем не менее, есть несколько вариантов использования pandarallel, которые принесут пользу ученым, работающим с данными. Хватит ждать операций с пандами и распараллелить их.#Python#Pandas#Machine Learning

Источник

+1
2
+1
0
+1
0
+1
0
+1
0

Ответить

Ваш адрес email не будет опубликован. Обязательные поля помечены *