СОВЕТЫ ПО ПРОГРАММИРОВАНИЮ НА ПИТОНЕ

Панды 2.0 против полярников: окончательная битва

Углубленный анализ синтаксиса, скорости и удобства использования между Pandas 2.0 и Polars 0.17.0

Введение

Имея дело с огромными наборами данных, большинству из нас приходилось сидеть часами, пока выполнялся наш код Pandas. Здесь пригодится библиотека Polars.

Polars — это молниеносная библиотека, которая может обрабатывать кадры данных значительно быстрее, чем Pandas.

За последний месяц мы видели огромные релизы этих двух библиотек, которые заявляют о значительном приросте скорости. Только что выпущенный Pandas 2.0 поддерживает Apache Arrows, что приводит к повышению производительности. Однако несколько основных операций по-прежнему выполняются быстрее с массивами NumPy. Версия Polaris 0.17.0, выпущенная на прошлой неделе, также улучшила производительность[1].

  1. Встроенная поддержка Rust: Polars написан на Rust. Способность Rust немедленно компилироваться в машинный код без использования интерпретатора может сделать его быстрее, чем Python.
  2. Распараллеливание: Polars использует многопоточность. Это позволяет выполнять векторизованные операции, которые могут выполняться параллельно на нескольких ядрах ЦП.
  3. Python для интерфейса: Polars можно использовать в качестве библиотеки Python, предоставляя простой в использовании интерфейс для обработки данных, используя преимущества Rust в плане производительности.
  4. Ленивая оценка: Polars поддерживает два API: ленивую и активную оценку (используется пандами). При ленивом вычислении запрос выполняется только тогда, когда это необходимо. Во время активной оценки запрос выполняется немедленно.

В этом посте я расскажу о

  1. Сравнение скорости Pandas 2.0 (с Numpy и Pyarrow в качестве серверной части) и Polars 0.17.0.
  2. Как без труда писать простой и сложный код Pandas с помощью революционной библиотеки Polars.

Мы проведем захватывающее соревнование по производительности между двумя библиотеками на 4-ядерных процессорах и 32 ГБ ОЗУ. Приготовьтесь поднять свои навыки анализа данных на новый уровень!

Начиная

Если у вас нет библиотеки на вашем локальном компьютере. Его можно установить с помощью команды pip

pip install polars==0.17.0 # Latest version

pip install pandas==2.0.0  # Latest pandas version

Для оценки производительности мы будем использовать синтетический набор данных, состоящий из 30 миллионов строк и 15 столбцов. Набор данных состоит из 8 категориальных и 7 числовых признаков и был создан искусственно. Доступ к набору данных можно получить здесь.

Пример набора данных показан ниже

# Pandas
train_pd.head()

#Polars
train_pl.head()

Импортируйте соответствующие библиотеки

import pandas as pd
import polars as pl
import numpy as np
import time

Чтение набора данных

Давайте сравним время чтения файла паркета обеих библиотек. Я использовал приведенный ниже код и использовал %%time, чтобы получить время выполнения кодов.

train_pd=pd.read_parquet('./train.parquet') #Pandas dataframe

train_pl=pl.read_parquet('./train.parquet') #Polars dataframe

Когда дело доходит до чтения файлов паркета, Polars и Pandas 2.0 работают одинаково по скорости. Однако Pandas (с использованием бэкэнда Numpy) занимает вдвое больше времени, чем Polars, для выполнения этой задачи.

Операции агрегации

Чтобы оценить функции агрегации, используйте приведенный ниже код, который дает общий код для сценариев, когда агрегации (минимум, максимум, среднее) должны быть рассчитаны для многих столбцов.

# pandas query
train_pd[nums].agg(['min','max','mean','median','std')
train[cats].agg(['nunique'])

# Polars query
train_pl.with_columns([
    pl.col(nums).min().suffix('_min'),
    pl.col(nums).max().suffix('_max'),
    pl.col(nums).mean().suffix('_mean'),
    pl.col(nums).median().suffix('_median'),
    pl.col(nums).std().suffix('_std'),
    pl.col(cats).nunique().suffix('_unique'),
])

Панды определенно лучше в синтаксисе и производительности для простых запросов, хотя разница в производительности минимальна. Следует отметить, что Polars может работать со списком функций, которые должны быть агрегированы с использованием одной и той же агрегации. тогда как в случае панд это не относится к ситуации, закодированной выше, поэтому я определил два кадра данных для сравнения.

Операции фильтрации и выбора

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

Запрос 1: подсчет уникальных значений для категорийных столбцов, когда nums_8 меньше 10.

# Polars filter and select
train_pl.filter(pl.col("num_8") <= 10).select(pl.col(cats).n_unique()) 

# Pandas filter and select
train_pd[train_pd['num_8']<=10][cats].nunique()

Запрос 2: среднее значение всех числовых столбцов, когда cat_1 равно 1.

# Polars filter and select
train_pl.filter(pl.col("cat_1") == 1).select(pl.col(nums).mean())

# Pandas filter and select
train_pd[train_pd['cat_1']==1][nums].mean()

С точки зрения производительности, Polars в 2–5 раз быстрее для числовых операций фильтрации, тогда как Pandas требует написания меньшего количества кода. Следует отметить, что Pandas медленнее работает со строками (категориальными функциями).

Групповые операции

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

Я проверил производительность этих библиотек на функциях, которые я определил ниже.

Функция 1: подсчитывать совокупные функции для cat_1

Функция 2:средняя функция для num_7

Функция 3: средние агрегированные характеристики для всех числовых столбцов.

Функция 4: подсчет агрегированных признаков для категориальных столбцов.

nums=['num_7','num_8', 'num_9', 'num_10', 'num_11', 'num_12', 'num_13', 'num_14','num_15']
cats=['cat_1', 'cat_2', 'cat_3', 'cat_4', 'cat_5', 'cat_6']

# Pandas Functions
Function_1= train_pd.groupby(['user'])['cat_1'].agg('count')   #Function 1
Function_2= train_pd.groupby(['user'])['num_7'].agg('mean')    #Function 2
Function_3= train_pd.groupby(['user'])[nums].agg('mean')       #Function 3
Function_4= train_pd.groupby(['user'])[cats].agg('count')      #Function 4


# Polars Functions
Function_1= train_pl.groupby('user').agg(pl.col('cat_1').count()) #Function 1
Function_2= train_pl.groupby('user').agg(pl.col('num_7').mean())  #Function 2
Function_3= train_pl.groupby('user').agg(pl.col(nums).mean())     #Function 3
Function_4= train_pl.groupby('user').agg(pl.col(cats).count())    #Function 4

Поляры кажутся лучшим выбором для группировки и агрегации. Следует также отметить, что Pandas 2.0 с бэкэндом Pyarrow во всех обстоятельствах заметно медленнее, чем как Polars, так и Pandas 2.0 (бэкэнд numpy).

Далее рассмотрим, как изменяется время при увеличении числа группирующих переменных с одной до пяти, как показано ниже.
Pandas 2.0 с поддержкой Pyarrow не показана на диаграмме, поскольку вычисление выражения занимает более 1000 секунд.

# PANDAS: TESTING GROUPING SPEED ON 5 COLUMNS
for cat in ['user', 'cat_1', 'cat_2', 'cat_3', 'cat_4']:
  cols+=[cat]
  st=time.time()
  temp=train_pd.groupby(cols)['num_7'].agg('mean')
  en=time.time()
  print(cat,':',en-st)


# POLARS: TESTING GROUPING SPEED ON 5 COLUMNS
for cat in ['user', 'cat_1', 'cat_2', 'cat_3', 'cat_4']:
  cols+=[cat]
  st=time.time()
  temp=train_pl.groupby(cols).agg(pl.col('num_7').mean())
  en=time.time()
  print(cat,':',en-st)
  del temp

Поляки снова победили! Pandas 2.0 (Numpy Backend) медленнее оценивает функции группировки. тогда как поддержка Pyarrow для Pandas 2.0 занимает более 1000 секунд.

Обратите внимание, что Pandas по умолчанию удаляет нулевые значения при группировке, тогда как библиотека Polars этого не делает.

Сортировка

Мы можем быстро отсортировать фрейм данных на основе одного или нескольких столбцов в порядке возрастания или убывания, используя приведенные ниже коды.

cols=['user','num_8'] # columns to be used for sorting

#Sorting in Polars
train_pl.sort(cols,descending=False)

# Sorting in Pandas
train_pd.sort_values(by=cols,ascending=True)

Polars по-прежнему является самой быстрой библиотекой для сложных случаев, таких как сортировка и группировка, как видно из гистограмм. В то время как Pandas может занять несколько минут, чтобы просто отсортировать фрейм данных, сложные функции сортировки могут быть оценены не более чем за 15 секунд в полярах.

Заключение

В заключение, выбор правильного инструмента для работы с большими наборами данных имеет важное значение для специалистов по данным. Наше исследование различий в производительности между Pandas и Polars подчеркивает преимущества и недостатки каждой библиотеки. В то время как Pandas более привлекателен синтаксически, Polars предлагает лучшую пропускную способность при работе с большими фреймами данных.

Важно отметить, что, поскольку Polars — более новая библиотека, некоторым людям может быть сложно перейти с Pandas. Однако решение об использовании той или иной библиотеки в конечном итоге зависит от размера ваших данных и того, насколько важна производительность для вашей работы. Понимая разницу между этими двумя мощными инструментами, специалисты по данным могут выбрать лучший вариант для своих конкретных потребностей и добиться более эффективного и действенного анализа данных.

Использованная литература:

[1] https://github.com/pola-rs/polars/releases/tag/py-0.17.0

[2] https://www.pola.rs/

[3] https://pandas.pydata.org/docs/dev/whatsnew/v2.0.0.html