Найти в Дзене
Хроники Data Engineer

PySpark vs Pandas | Наглядная разница

Оглавление

Всем привет! И в сегодняшнем посте мы рассмотрим 2 популярных инструмента для обработки данных PySpark и Pandas на примере сгенерированных данных в локальном режиме.

Очень часто слышу от людей, которые только-только пришли в область дата инженерии или ходят вокруг нее, что PySpark - это продвинутый Pandas. Отчасти, это так, но не совсем. Давайте разбираться.

Начнем с истории PySpark.

Логотип Spark. У PySpark его вообще нет.
Логотип Spark. У PySpark его вообще нет.
  • 2010 год: Apache Spark был создан в AMPLab Университета Беркли, но изначально его API был доступен только на языке Scala, на котором Spark был написан.
  • 2013 год: С ростом популярности Spark сообщество увидело необходимость поддержки более широкого круга языков программирования. Тогда был представлен интерфейс PySpark, который обеспечил доступ к возможностям Spark через язык Python.
  • 2014 год: Spark был передан сообществу Apache и стал полноценным проектом. PySpark продолжал развиваться, улучшая производительность и удобство для пользователей Python.

Продолжим историей Pandas.

-2

  • 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} секунд")

Запускаем код и получаем следующее время -

-3

То есть получается, что фильтрация и группировка миллиона записей выполнилась за 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()

Запускаем, и...

-4

Чтоооооооооо? 11.7 секунд? Те же самые операции? Да!

Давайте разбираться в чем прикол. А все очень просто. У PySpark в моменте строиться огромный кластер, хоть и локальный. То есть получается накладные расходы на инициализацию Spark занимают больше времени, чем само выполнение задачи.

К сожалению, я не могу проверить выполнение например на 500.000.000 строк. Почему? Не хватает оперативной памяти, о чем нам говорит Python.

-5

Но, тем не менее увеличим данные до 50.000.000 в обоих случаях и посмотрим время.

  • Pandas время: 3.1719448566436768 секунд
  • PySpark выполниться не смог. При 16 Гб оперативной памяти. Увы :(

Таким образом, там, где Pandas спокойно работает, PySpark выполниться не может. А, говорят, что PySpark умеет большие данные обрабатывать...

А при 250.000.000 тысяч строк...

  • Pandas время: 25.901596784591675 секунд
-6

Какой вывод можно сделать? Pandas хорош практически в 100% случаях, если данные можно обработать локально. PySpark хорош, только если "игра стоит свеч". То есть в кластерном, но не локальном режиме. Иначе раскрыть его просто напросто не получится. Слишком много у него служебных служб и ресурсов. И это при том, что PySpark'у были выделены все свободные ядра компьютера из имеющихся 10.

И не стоит гневаться на PySpark, потому что это выглядит как так, если бы Вы купили себе 750 л.с. машину и ездите на ней в пробках. И только и делаете, что заправляете ее и разогнаться негде. Не стоит загонять инструмент туда, где он не сможет раскрыться. А если уж загоняете - то не загоняйтесь :)

Спасибо за внимание!

Мы на дзене | Мы в телеграмме | Мы на Stepik