Оптимизация производительности Pandas
Pandas — очень мощный инструмент анализа данных, но когда наборы данных становятся большими, часто возникают узкие места производительности.
Чтобы повысить эффективность Pandas при обработке крупномасштабных данных, необходимо понимать и применять некоторые методы оптимизации производительности.
Оптимизация производительности Pandas включает несколько аспектов, в том числе оптимизацию типов данных, избегание ненужных циклов, использование векторизованных операций, оптимизацию индексов и загрузку больших наборов данных по частям.
Ниже мы подробно рассмотрим несколько методов оптимизации производительности Pandas.
Используйте подходящие типы данных
Типы данных в Pandas (dtype) напрямую влияют на использование памяти и скорость вычислений. Выбор подходящих типов данных может значительно уменьшить использование памяти и ускорить вычисления.
1. Используйте подходящие числовые типы
Стандартный числовой тип в Pandas —int64иfloat64, но для большинства данных это может привести к излишнему расходу памяти. Можно использовать меньшие типы, напримерint8, int16, float32и т. д.
| Метод | Описание |
|---|---|
astype() |
Используется для преобразования типа данных столбца |
downcast |
Понизить тип данных, например, преобразоватьint64с понижением доint32илиint16 |
Пример
# Пример данных
df = pd.DataFrame({'A': [100, 200, 300, 400], 'B': [1000, 2000, 3000, 4000]})
# Преобразовать типы данных столбцов в меньшие типы данных
df['A'] = df['A'].astype('int16')
df['B'] = df['B'].astype('int32')
print(df.dtypes)
Вывод:
A int16 B int32 dtype: object
2. Используйте для символьных данныхcategorytype
Для строковых столбцов с повторяющимися значениями можно использоватьcategoryтип для сокращения потребления памяти.categoryЭтот тип хранит в памяти целочисленные индексы, а не сами строки.
Пример
df = pd.DataFrame({'Category': ['A', 'B', 'A', 'C', 'B', 'A']})
# Используйте тип category
df['Category'] = df['Category'].astype('category')
print(df.dtypes)
Вывод:
Category category dtype: object
Используйте векторизованные операции вместо циклов
Одно из главных преимуществ Pandas — возможность использовать векторизованные операции для быстрых пакетных вычислений. В Pandas старайтесь избегать нативных циклов Python и использовать встроенные функции Pandas, которые могут задействовать внутренние оптимизации для быстрых вычислений.
Пример
# Пример данных
df = pd.DataFrame({'A': [1, 2, 3, 4], 'B': [5, 6, 7, 8]})
# Используйте векторизованные операции, избегайте циклов
df['C'] = df['A'] + df['B']
print(df)
Вывод:
A B C 0 1 5 6 1 2 6 8 2 3 7 10 3 4 8 12
По сравнению с обработкой данных строка за строкой использование векторизованных операций Pandas может значительно повысить скорость вычислений.
3. Используйтеapply()иapplymap()Оптимизация
Pandas предоставляетapply()иapplymap()методы, которые позволяют применять функции к строкам или столбцам в DataFrame и более эффективны, чем циклы.
Пример
df['D'] = df['A'].apply(lambda x: x ** 2)
print(df)
Вывод:
A B C D 0 1 5 6 1 1 2 6 8 4 2 3 7 10 9 3 4 8 12 16
apply()Он подходит для обработки одномерных данных,applymap()тогда как он применяет функцию к каждому элементу в DataFrame и подходит для двумерных данных.
Пример
df = df.applymap(lambda x: x * 10)
print(df)
Вывод:
A B C D 0 10 50 60 10 1 20 60 80 40 2 30 70 100 90 3 40 80 120 160
Используйте подходящие индексы
Индексы Pandas могут повысить скорость поиска данных, особенно когда требуется множество поисков или объединений данных, и индексы могут значительно повысить эффективность. Для больших наборов данных обеспечение подходящих индексов и сокращение ненужных операций с индексами может повысить производительность.
Пример
df = pd.DataFrame({'A': [1, 2, 3, 4], 'B': [5, 6, 7, 8]})
df.set_index('A', inplace=True)
# Быстрый поиск по индексу
print(df.loc[2])
Вывод:
B 6 Name: 2, dtype: int64
Загружайте большие наборы данных частями
Когда набор данных слишком велик, загрузка всего набора данных может потреблять много памяти и даже привести к переполнению памяти. В этом случае можно снизить нагрузку на память, считывая данные частями.
Pandas предоставляетchunksizeпараметр, который позволяет загружать данные частями при чтении файлов CSV или Excel.
Пример
chunksize = 10000
for chunk in pd.read_csv('large_file.csv', chunksize=chunksize):
# Обработать каждый фрагмент данных
process(chunk)
Dask и Vaex — это две библиотеки, которые могут обрабатывать наборы данных, размер которых превышает объём памяти. Они совместимы с Pandas, поддерживают многопоточность и распределённые вычисления, а также могут эффективно обрабатывать очень большие наборы данных.
Пример
# Использовать Dask для чтения большого набора данных
df = dd.read_csv('large_file.csv')
# Выполнить вычислительные операции
df.groupby('category').sum().compute()
ЧерезnumbaУскорение вычислений
numba— это JIT-компилятор, который может ускорить код Python. За счёт ускорения кода для обработки данных можно значительно повысить производительность. Особенно для вычислительно интенсивных операций, таких как циклы и численные расчёты,numbaэто может значительно увеличить скорость.
Пример
import pandas as pd
# Пример функции
@numba.jit
def calculate_square(x):
return x ** 2
# Использовать numba для ускорения вычислений
df = pd.DataFrame({'A': [1, 2, 3, 4]})
df['B'] = df['A'].apply(calculate_square)
print(df)
Избегайте цепочного присваивания
Цепочное присваивание — одна из распространённых ловушек производительности в Pandas. Оно может вызывать ненужные побочные эффекты и обычно замедляет выполнение. Лучше всего использовать явное присваивание и избегать множественных присваиваний в одной строке.
Пример
df['A'][df['A'] > 2] = 0
# Правильный способ присваивания:
df.loc[df['A'] > 2, 'A'] = 0
Оптимизируйте операции слияния
При слиянии нескольких DataFrame используйтеmerge()илиconcat()нужно уделить внимание оптимизации операции слияния, особенно при обработке больших наборов данных. Можно использоватьonиhowпараметр, чтобы явно указать метод слияния и избежать ненужных вычислений.
Пример
# Используйте подходящий метод слияния
df1 = pd.DataFrame({'ID': [1, 2, 3], 'Value': ['A', 'B', 'C']})
df2 = pd.DataFrame({'ID': [1, 2, 3], 'Value': ['X', 'Y', 'Z']})
# Используйте параметр on для слияния
merged_df = pd.merge(df1, df2, on='ID', how='inner')
print(merged_df)
Вывод:
ID Value_x Value_y 0 1 A X 1 2 B Y 2 3 C ZДругие расширения