В этом руководстве мы рассмотрим Modin — мощную замену Pandas, которая использует параллельные вычисления для значительного ускорения рабочих процессов с данными. Импортируя `modin.pandas` как `pd`, мы преобразуем наш код Pandas в мощную систему распределённых вычислений. Наша цель — понять, как Modin работает с реальными операциями с данными, такими как `groupby`, `joins`, очистка и анализ временных рядов, при этом используя Google Colab. Мы сравниваем производительность каждой задачи со стандартной библиотекой Pandas, чтобы увидеть, насколько быстрее и эффективнее может быть Modin.
Установка Modin
Мы начинаем с установки Modin с бэкендом Ray, который обеспечивает параллельную работу операций Pandas в Google Colab. Мы подавляем ненужные предупреждения, чтобы вывод был чистым и понятным. Затем мы импортируем все необходимые библиотеки и инициализируем Ray с 2 процессорами, подготавливая нашу среду для распределённой обработки DataFrames.
“`python
!pip install “modin[ray]” -q
import warnings
warnings.filterwarnings(‘ignore’)
import numpy as np
import pandas as pd
import time
import os
from typing import Dict, Any
import modin.pandas as mpd
import ray
ray.init(ignorereiniterror=True, num_cpus=2)
print(f”Ray initialized with {ray.cluster_resources()}”)
“`
Определение функции для сравнения производительности
Мы определяем функцию `benchmark_operation` для сравнения времени выполнения конкретной задачи с использованием как Pandas, так и Modin. Запуская каждую операцию и записывая её продолжительность, мы рассчитываем ускорение, которое предлагает Modin. Это даёт нам чёткий и измеримый способ оценить прирост производительности для каждой операции, которую мы тестируем.
“`python
def benchmarkoperation(pandasfunc, modinfunc, data, operationname: str) -> Dict[str, Any]:
“””Compare pandas vs modin performance”””
start_time = time.time()
pandasresult = pandasfunc(data[‘pandas’])
pandastime = time.time() – starttime
start_time = time.time()
modinresult = modinfunc(data[‘modin’])
modintime = time.time() – starttime
speedup = pandastime / modintime if modin_time > 0 else float(‘inf’)
print(f”\n{operation_name}:”)
print(f” Pandas: {pandas_time:.3f}s”)
print(f” Modin: {modin_time:.3f}s”)
print(f” Speedup: {speedup:.2f}x”)
return {
‘operation’: operation_name,
‘pandastime’: pandastime,
‘modintime’: modintime,
‘speedup’: speedup
}
“`
Генерация большого набора данных
Мы определяем функцию `createlargedataset` для генерации богатого синтетического набора данных с 500 000 строк, который имитирует реальные данные транзакций, включая информацию о клиентах, моделях покупок и временных метках. Мы создаём версии этого набора данных как для Pandas, так и для Modin, чтобы можно было сравнить их бок о бок. После создания данных мы отображаем их размеры и объём памяти, готовя почву для сложных операций Modin.
“`python
def createlargedataset(rows: int = 1000000):
“””Generate synthetic dataset for testing”””
np.random.seed(42)
data = {
‘customer_id’: np.random.randint(1, 50000, rows),
‘transaction_amount’: np.random.exponential(50, rows),
‘category’: np.random.choice([‘Electronics’, ‘Clothing’, ‘Food’, ‘Books’, ‘Sports’], rows),
‘region’: np.random.choice([‘North’, ‘South’, ‘East’, ‘West’], rows),
‘date’: pd.date_range(‘2020-01-01′, periods=rows, freq=’H’),
‘is_weekend’: np.random.choice([True, False], rows, p=[0.3, 0.7]),
‘rating’: np.random.uniform(1, 5, rows),
‘quantity’: np.random.poisson(3, rows) + 1,
‘discount_rate’: np.random.beta(2, 5, rows),
‘age_group’: np.random.choice([’18-25′, ’26-35′, ’36-45′, ’46-55′, ’55+’], rows)
}
pandas_df = pd.DataFrame(data)
modin_df = mpd.DataFrame(data)
print(f”Dataset created: {rows:,} rows × {len(data)} columns”)
print(f”Memory usage: {pandasdf.memoryusage(deep=True).sum() / 10242:.1f} MB”)
return {‘pandas’: pandasdf, ‘modin’: modindf}
dataset = createlargedataset(500_000)
“`
Сложные операции `groupby`
Мы определяем функцию `complex_groupby` для выполнения многоуровневых операций `groupby` над набором данных, группируя его по категориям и регионам. Затем мы агрегируем несколько столбцов, используя такие функции, как `sum`, `mean`, стандартное отклонение и `count`. Наконец, мы сравниваем эту операцию как в Pandas, так и в Modin, чтобы измерить, насколько быстрее Modin выполняет такие сложные агрегации `groupby`.
“`python
def complex_groupby(df):
return df.groupby([‘category’, ‘region’]).agg({
‘transaction_amount’: [‘sum’, ‘mean’, ‘std’, ‘count’],
‘rating’: [‘mean’, ‘min’, ‘max’],
‘quantity’: ‘sum’
}).round(2)
groupbyresults = benchmarkoperation(
complexgroupby, complexgroupby, dataset, “Complex GroupBy Aggregation”
)
“`
Продвинутая очистка данных
Мы определяем функцию `advancedcleaning` для имитации реального процесса предварительной обработки данных. Сначала мы удаляем выбросы, используя метод IQR, чтобы обеспечить более чистые данные. Затем мы выполняем разработку признаков, создавая новую метрику под названием `transactionscore` и помечая транзакции с высокой стоимостью. Наконец, мы сравниваем эту логику очистки, используя как Pandas, так и Modin, чтобы увидеть, как они справляются со сложными преобразованиями больших наборов данных.
“`python
def advanced_cleaning(df):
df_clean = df.copy()
Q1 = dfclean[‘transactionamount’].quantile(0.25)
Q3 = dfclean[‘transactionamount’].quantile(0.75)
IQR = Q3 – Q1
dfclean = dfclean[
(dfclean[‘transactionamount’] >= Q1 – 1.5 * IQR) &
(dfclean[‘transactionamount’] <= Q3 + 1.5 * IQR)
]
dfclean[‘transactionscore’] = (
dfclean[‘transactionamount’] dfclean[‘rating’] dfclean[‘quantity’]
)
dfclean[‘ishighvalue’] = dfclean[‘transactionamount’] > dfclean[‘transaction_amount’].median()
return df_clean
cleaningresults = benchmarkoperation(
advancedcleaning, advancedcleaning, dataset, “Advanced Data Cleaning”
)
“`
Анализ временных рядов
Мы определяем функцию `timeseriesanalysis` для изучения ежедневных тенденций путём пересчёта данных транзакций во времени. Мы устанавливаем столбец даты в качестве индекса, вычисляем ежедневные агрегаты, такие как сумма, среднее значение, количество и среднее значение рейтинга, и компилируем их в новый DataFrame. Чтобы зафиксировать более долгосрочные закономерности, мы также добавляем скользящее среднее за 7 дней. Наконец, мы сравниваем этот конвейер временных рядов с помощью как Pandas, так и Modin, чтобы сравнить их эффективность на временных данных.
“`python
def timeseriesanalysis(df):
df_ts = df.copy()
dfts = dfts.set_index(‘date’)
dailysum = dfts.groupby(dfts.index.date)[‘transactionamount’].sum()
dailymean = dfts.groupby(dfts.index.date)[‘transactionamount’].mean()
dailycount = dfts.groupby(dfts.index.date)[‘transactionamount’].count()
dailyrating = dfts.groupby(df_ts.index.date)[‘rating’].mean()
daily_stats = type(df)({
‘transactionsum’: dailysum,
‘transactionmean’: dailymean,
‘transactioncount’: dailycount,
‘ratingmean’: dailyrating
})
dailystats[‘rollingmean7d’] = dailystats[‘transaction_sum’].rolling(window=7).mean()
return daily_stats
tsresults = benchmarkoperation(
timeseriesanalysis, timeseriesanalysis, dataset, “Time Series Analysis”
)
“`
Создание справочных данных для объединений
Мы определяем функцию `createlookupdata` для генерации двух справочных таблиц: одной для категорий продуктов и другой для регионов, каждая из которых содержит соответствующие метаданные, такие как ставки комиссионных, налоговые ставки и стоимость доставки. Мы готовим эти справочные таблицы как в формате Pandas, так и в формате Modin, чтобы позже использовать их в операциях объединения и сравнить их производительность в обеих библиотеках.
“`python
def createlookupdata():
“””Create lookup tables for joins”””
categories_data = {
‘category’: [‘Electronics’, ‘Clothing’, ‘Food’, ‘Books’, ‘Sports’],
‘commission_rate’: [0.15, 0.20, 0.10, 0.12, 0.18],
‘target_audience’: [‘Tech Enthusiasts’, ‘Fashion Forward’, ‘Food Lovers’, ‘Readers’, ‘Athletes’]
}
regions_data = {
‘region’: [‘North’, ‘South’, ‘East’, ‘West’],
‘tax_rate’: [0.08, 0.06, 0.09, 0.07],
‘shipping_cost’: [5.99, 4.99, 6.99, 5.49]
}
return {
‘pandas’: {
‘categories’: pd.DataFrame(categories_data),
‘regions’: pd.DataFrame(regions_data)
},
‘modin’: {
‘categories’: mpd.DataFrame(categories_data),
‘regions’: mpd.DataFrame(regions_data)
}
}
lookupdata = createlookup_data()
“`
Продвинутые объединения
Мы определяем функцию `advancedjoins` для обогащения нашего основного набора данных путём объединения его со справочными таблицами категорий и регионов. После выполнения объединений мы вычисляем дополнительные поля, такие как `commissionamount`, `taxamount` и `totalcost`, чтобы имитировать реальные финансовые расчёты. Наконец, мы сравниваем весь этот конвейер объединений и вычислений, используя как Pandas, так и Modin, чтобы оценить, насколько хорошо Modin справляется со сложными многошаговыми операциями.
“`python
def advanced_joins(df, lookup):
result = df.merge(lookup[‘categories’], on=’category’, how=’left’)
result = result.merge(lookup[‘regions’], on=’region’, how=’left’)
result[‘commissionamount’] = result[‘transactionamount’] * result[‘commission_rate’]
result[‘taxamount’] = result[‘transactionamount’] * result[‘tax_rate’]
result[‘totalcost’] = result[‘transactionamount’] + result[‘taxamount’] + result[‘shippingcost’]
return result
joinresults = benchmarkoperation(
lambda df: advancedjoins(df, lookupdata[‘pandas’]),
lambda df: advancedjoins(df, lookupdata[‘modin’]),
dataset,
“Advanced Joins & Calculations”
)
“`
Сравнение использования памяти
Мы сдвигаем фокус на использование памяти и печатаем заголовок раздела, чтобы выделить это сравнение. В функции `getmemoryusage` мы вычисляем объём памяти, занимаемой как Pandas, так и Modin DataFrames, используя их внутренние методы `memoryusage`. Мы обеспечиваем совместимость с Modin, проверяя наличие атрибута `to_pandas`. Это помогает нам оценить, насколько эффективно Modin обрабатывает память по сравнению с Pandas, особенно с большими наборами данных.
“`python
def getmemoryusage(df, name):
“””Get memory usage of dataframe”””
if hasattr(df, ‘topandas’):
memorymb = df.memoryusage(deep=True).sum() / 10242
else:
memorymb = df.memoryusage(deep=True).sum() / 10242
print(f”{name} memory usage: {memory_mb:.1f} MB”)
return memory_mb
pandasmemory = getmemory_usage(dataset[‘pandas’], “Pandas”)
modinmemory = getmemory_usage(dataset[‘modin’], “Modin”)
“`
Резюме производительности
Мы суммируем результаты бенчмаркинга по всем протестированным операциям, рассчитывая среднее ускорение, которого Modin достиг по сравнению с Pandas. Мы также выделяем наиболее эффективную операцию, предоставляя чёткое представление о том, где Modin работает лучше всего. Затем мы делимся набором лучших практик для эффективного использования Modin, включая советы по совместимости, профилированию производительности и преобразованию между Pandas и Modin.
“`python
results = [groupbyresults, cleaningresults, tsresults, joinresults]
avg_speedup = sum(r[‘speedup’] for r in results) / len(results)
print(f”\nAverage Speedup: {avg_speedup:.2f}x”)
print(f”Best Operation: {max(results, key=lambda x: x[‘speedup’])[‘operation’]} “
f”({max(results, key=lambda x: x[‘speedup’])[‘speedup’]:.2f}x)”)
print(“\nDetailed Results:”)
for result in results:
print(f” {result[‘operation’]}: {result[‘speedup’]:.2f}x speedup”)
“`
Лучшие практики использования Modin
1. Используйте `import modin.pandas as pd` для полной замены Pandas.
2. Modin лучше всего работает с операциями на больших наборах данных (>100 МБ).
3. Бэкенд Ray наиболее стабилен; Dask для распределённых кластеров.
4. Некоторые функции Pandas могут автоматически переходить на Pandas.
5. Используйте `.to_pandas()` для преобразования Modin DataFrame в Pandas при необходимости.
6. Профилируйте свою конкретную рабочую нагрузку — скорость зависит от типа операции.
7. Modin отлично справляется с операциями `groupby`, `join`, `apply` и операциями ввода-вывода больших данных.
Ray завершает работу.
Заключение
Мы увидели, как Modin может ускорить наши рабочие процессы Pandas с минимальными изменениями в коде. Независимо от того, идёт ли речь о сложных агрегациях, анализе временных рядов или операциях с интенсивным использованием памяти, Modin обеспечивает масштабируемую производительность для повседневных задач, особенно на таких платформах, как Google Colab. Благодаря мощности Ray и почти полной совместимости с API Pandas, Modin упрощает работу с большими наборами данных.
Вопросы по тексту статьи:
1. Какие преимущества предлагает Modin по сравнению с Pandas для работы с большими наборами данных?
В статье утверждается, что Modin может значительно ускорить рабочие процессы с данными за счёт использования параллельных вычислений. В тексте приводится пример генерации большого набора данных с 500 000 строк и сравнение производительности операций groupby, очистки данных и анализа временных рядов между Pandas и Modin.
2. Какие функции Modin позволяют ему эффективно работать с операциями groupby и объединениями?
В статье описывается, как Modin используется для выполнения многоуровневых операций groupby и продвинутых объединений. Для этого применяются функции, такие как `complexgroupby` и `advancedjoins`, которые позволяют агрегировать данные и объединять справочные таблицы.
3. Как Modin влияет на использование памяти при работе с большими наборами данных?
В статье упоминается, что Modin обеспечивает эффективное использование памяти при работе с большими наборами данных. В тексте приводится пример расчёта объёма памяти, занимаемой DataFrames в Pandas и Modin, с помощью функции `getmemoryusage`.
4. Какие лучшие практики использования Modin предлагаются в статье?
В статье перечислены несколько лучших практик использования Modin:
* использование `import modin.pandas as pd` для полной замены Pandas;
* Modin лучше всего работает с операциями на больших наборах данных (>100 МБ);
* бэкенд Ray наиболее стабилен;
* некоторые функции Pandas могут автоматически переходить на Pandas;
* использование `.to_pandas()` для преобразования Modin DataFrame в Pandas при необходимости;
* профилирование своей конкретной рабочей нагрузки;
* Modin отлично справляется с операциями `groupby`, `join`, `apply` и операциями ввода-вывода больших данных.
5. Какие выводы можно сделать из сравнения производительности Pandas и Modin в статье?
В статье приводится сравнение производительности различных операций между Pandas и Modin. В результате сравнения делается вывод, что Modin обеспечивает масштабируемую производительность для повседневных задач, особенно на таких платформах, как Google Colab.