Всем привет! И в сегодняшнем посте мы рассмотрим 2 популярных инструмента для обработки данных PySpark и Pandas на примере сгенерированных данных в локальном режиме.
Очень часто слышу от людей, которые только-только пришли в область дата инженерии или ходят вокруг нее, что PySpark - это продвинутый Pandas. Отчасти, это так, но не совсем. Давайте разбираться.
Начнем с истории PySpark.
- 2010 год: Apache Spark был создан в AMPLab Университета Беркли, но изначально его API был доступен только на языке Scala, на котором Spark был написан.
- 2013 год: С ростом популярности Spark сообщество увидело необходимость поддержки более широкого круга языков программирования. Тогда был представлен интерфейс PySpark, который обеспечил доступ к возможностям Spark через язык Python.
- 2014 год: Spark был передан сообществу Apache и стал полноценным проектом. PySpark продолжал развиваться, улучшая производительность и удобство для пользователей Python.
Продолжим историей Pandas.
- 2008 год: Библиотека Pandas была создана Уэслом МакКинни (Wes McKinney), который работал в инвестиционной компании AQR Capital Management. Уэслу нужно было более мощное средство для работы с данными на Python, чем существовавшие в то время инструменты. Он начал разрабатывать Pandas как внутренний инструмент для финансового анализа.
- 2009 год: Pandas была выпущена как проект с открытым исходным кодом. Библиотека быстро завоевала популярность в сообществе Python благодаря интуитивному интерфейсу для работы с табличными данными, предоставляя простые методы для манипуляции и анализа данных, что сделало её удобной для финансовых и статистических вычислений.
- 2010–2011 годы: Pandas получила активное развитие благодаря поддержке со стороны других разработчиков. В этот период был создан и улучшен основной функционал, включая поддержку DataFrame — структуры данных, которая позволяла работать с табличными данными, аналогично таблицам в Excel или базам данных.
- 2012 год: Pandas получила широкое признание в научном сообществе благодаря возможности работать с данными из различных источников (CSV, Excel, SQL) и мощным методам для фильтрации, агрегирования и анализа данных.
- 2015 год: Pandas стала одним из ключевых инструментов в экосистеме Python для анализа данных и машинного обучения. Вместе с библиотеками NumPy, Matplotlib и SciPy она вошла в стандартный набор инструментов для анализа данных, используемый как в исследовательской, так и в промышленной сфере.
- 2017 год: Был выпущен Pandas 1.0, что ознаменовало её зрелость как библиотеки с широкими возможностями для работы с большими наборами данных и удобным API. В этот период библиотека продолжила улучшаться, добавляя поддержку многопоточности и оптимизации.
То есть pandas вышел раньше и это его первый плюс. Как следствие - большая популярность.
Двигаемся дальше и сравним их по архитектуре, оно же внутреннее устройство. Не переключайтесь - на самое сладкое оставим временное сравнение в обработке одинакового набора данных.
Pandas
- Pandas работает на одном компьютере, и все данные загружаются в оперативную память. Это делает его пригодным для небольших и средних наборов данных, которые могут уместиться в памяти (обычно до нескольких миллионов строк).
- Архитектура Pandas не предназначена для работы с данными, превышающими объём оперативной памяти, поэтому при больших объёмах данных могут возникнуть проблемы с производительностью и памятью.
PySpark
- PySpark может работать в распределенном режиме. Но, даже в локальном режиме с теми же ресурсами, что и у Pandas он выиграет.
- PySpark применяет концепцию ленивых вычислений: операции с данными выполняются только тогда, когда запрашивается результат. Это позволяет Spark оптимизировать выполнение плана операций, что ускоряет обработку.
- И в PySpark мы можем регулировать оперативную память, разбавляя ее диском, за счет метода persist.
Тут балл за PySpark'ом.
И, наконец, рассмотрим сравнение в количественных данных и замерим выполнение. Представим, что оба инструмента у Вас уже установлены. Операции будут одинаковые. Ресурсы в определенный момент времени будут забронированы за программой. Данных будет 1.000.000 строк. Начнем с Pandas. Оба инструменты с дефолтной сборкой из коробки, без каких-либо конфигов. То есть прямо сразу в лоб.
Вот структура данных:
- id: Уникальный идентификатор строки.
- value1: Случайные целые числа в диапазоне от 0 до 100.
- value2: Также случайные целые числа в диапазоне от 0 до 100.
- category: Случайная категория (одна из 'A', 'B', 'C', 'D').
Pandas
import pandas as pd
import numpy as np
import time
def generate_data_pandas(rows):
data = {
'id': np.arange(rows),
'value1': np.random.randint(0, 100, size=rows),
'value2': np.random.randint(0, 100, size=rows),
'category': np.random.choice(['A', 'B', 'C', 'D'], size=rows)
}
return pd.DataFrame(data)
def process_pandas(df):
df_filtered = df[df['value1'] > 50]
df_grouped = df_filtered.groupby('category')['value2'].mean()
return df_grouped
rows = 10**6
start_time = time.time()
pandas_df = generate_data_pandas(rows)
pandas_result = process_pandas(pandas_df)
pandas_time = time.time() - start_time
print(f"Pandas время: {pandas_time} секунд")
Запускаем код и получаем следующее время -
То есть получается, что фильтрация и группировка миллиона записей выполнилась за 0.06 секунд? Да!
PySpark
from pyspark.sql import SparkSession
from pyspark.sql.functions import col
import pandas as pd
import numpy as np
import time
spark = SparkSession.builder.master("local[*]").appName("PySparkVsPandas").getOrCreate()
def generate_data_pandas(rows):
data = {
'id': np.arange(rows),
'value1': np.random.randint(0, 100, size=rows),
'value2': np.random.randint(0, 100, size=rows),
'category': np.random.choice(['A', 'B', 'C', 'D'], size=rows)
}
return pd.DataFrame(data)
def generate_data_pyspark(rows):
df_pandas = generate_data_pandas(rows)
return spark.createDataFrame(df_pandas)
def process_pyspark(df):
df_filtered = df.filter(col('value1') > 50)
df_grouped = df_filtered.groupBy('category').agg({'value2': 'mean'})
return df_grouped
rows = 10**6
start_time = time.time()
pyspark_df = generate_data_pyspark(rows)
pyspark_result = process_pyspark(pyspark_df)
pyspark_time = time.time() - start_time
print(f"PySpark время: {pyspark_time} секунд")
spark.stop()
Запускаем, и...
Чтоооооооооо? 11.7 секунд? Те же самые операции? Да!
Давайте разбираться в чем прикол. А все очень просто. У PySpark в моменте строиться огромный кластер, хоть и локальный. То есть получается накладные расходы на инициализацию Spark занимают больше времени, чем само выполнение задачи.
К сожалению, я не могу проверить выполнение например на 500.000.000 строк. Почему? Не хватает оперативной памяти, о чем нам говорит Python.
Но, тем не менее увеличим данные до 50.000.000 в обоих случаях и посмотрим время.
- Pandas время: 3.1719448566436768 секунд
- PySpark выполниться не смог. При 16 Гб оперативной памяти. Увы :(
Таким образом, там, где Pandas спокойно работает, PySpark выполниться не может. А, говорят, что PySpark умеет большие данные обрабатывать...
А при 250.000.000 тысяч строк...
- Pandas время: 25.901596784591675 секунд
Какой вывод можно сделать? Pandas хорош практически в 100% случаях, если данные можно обработать локально. PySpark хорош, только если "игра стоит свеч". То есть в кластерном, но не локальном режиме. Иначе раскрыть его просто напросто не получится. Слишком много у него служебных служб и ресурсов. И это при том, что PySpark'у были выделены все свободные ядра компьютера из имеющихся 10.
И не стоит гневаться на PySpark, потому что это выглядит как так, если бы Вы купили себе 750 л.с. машину и ездите на ней в пробках. И только и делаете, что заправляете ее и разогнаться негде. Не стоит загонять инструмент туда, где он не сможет раскрыться. А если уж загоняете - то не загоняйтесь :)
Спасибо за внимание!
Мы на дзене | Мы в телеграмме | Мы на Stepik