Эффективная обработка данных с помощью Apply() в Pandas

Функция apply() - это мощный инструмент в Python для анализа данных и манипулирования ими. Это ценный инструмент для инструментария любого аналитика, поскольку он может быть легко интегрирован с другими функциями Pandas и пользовательскими функциями для выполнения сложных преобразований данных. В этой статье мы узнаем, как использовать функцию apply() в Pandas для эффективной и гибкой обработки данных.

Обзор функции Apply()

Функция apply() позволяет выполнять ряд преобразований ваших данных. Вы можете определить свою собственную функцию для определенных задач, таких как манипуляции со строками, сложные операции или пользовательские вычисления. После определения вы можете использовать apply() их в своем DataFrame без необходимости кодировать их снова каждый раз, когда вам нужно их использовать.

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

Функцию apply()также можно использовать со встроенными функциями, предварительно упакованными в Python. Pandas Series и DataFrames совместимы с использованием apply().

Использование Apply() в серии

Давайте определим серию среднемесячных температур (в градусах Цельсия) для города за год, импортировав пакет Pandas и используя класс Series():

import pandas as pd

city_temps = pd.Series([1, 4, 8, 9, 14, 25, 31, 35, 32, 25, 11, 2])

Мы можем создать пользовательскую функцию для преобразования этих температур в шкалу Фаренгейта:

def celsius_to_fahrenheit(celsius):
    fahrenheit = (celsius * 9/5) + 32
    return fahrenheit

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

temp_fahrenheit = city_temps.apply(celsius_to_fahrenheit)
print(temp_fahrenheit)

Результатом является ряд, содержащий преобразованные значения городских температур:

0     33.8
1     39.2
2     46.4
3     48.2
4     57.2
5     77.0
6     87.8
7     95.0
8     89.6
9     77.0
10    51.8
11    35.6
dtype: float64

Применение apply() к DataFrame

Использование apply() обеспечивает гибкость добавления или управления столбцами в Pandas DataFrames. Рассмотрим DataFrame со среднемесячными температурами в течение года для двух городов:

data = {'City 1': [1, 4, 8, 9, 14, 25, 31, 35, 32, 25, 11, 2],
        'City 2': [19, 23, 30, 31, 35, 40, 45, 39, 30, 25, 15, 10]
       }
# Create the DataFrame
df = pd.DataFrame(data)
print(df)

DataFrame выглядит следующим образом:

    City 1  City 2
0        1      19
1        4      23
2        8      30
3        9      31
4       14      35
5       25      40
6       31      45
7       35      39
8       32      30
9       25      25
10      11      15
11       2      10

Мы можем использовать apply()нашу функцию в dfDataFrame и создать новый столбец City 1 Fahrenheit:

df['City 1 Fahrenheit'] = df['City 1'].apply(celsius_to_fahrenheit)

# Print the DataFrame
print(df)

Трансформация прошла успешно:

    City 1  City 2  City 1 Fahrenheit
0        1      19               33.8
1        4      23               39.2
2        8      30               46.4
3        9      31               48.2
4       14      35               57.2
5       25      40               77.0
6       31      45               87.8
7       35      39               95.0
8       32      30               89.6
9       25      25               77.0
10      11      15               51.8
11       2      10               35.6

Важным примечанием здесь является использование параметра axisвнутри apply()функции, который указывает, хотим ли мы выполнить операцию со строками или столбцами DataFrame. При указании axis=0операция axis=1применяется к каждому столбцу, а к каждой строке. В нашем предыдущем примере axis=0использовалось значение по умолчанию, поскольку мы не передавали значение для axis. Это применило нашу функцию к каждому столбцу и вернуло значение для каждой строки.

Давайте явно передадим axis=1 нашей apply() пользовательской функции все столбцы в DataFrame. Мы создадим два новых столбца, применяя преобразование к каждой строке.

data = {'City 1': [1, 4, 8, 9, 14, 25, 31, 35, 32, 25, 11, 2],
        'City 2': [19, 23, 30, 31, 35, 40, 45, 39, 30, 25, 15, 10]
       }

df = pd.DataFrame(data)

df[['City 1 Fahrenheit', 'City 2 Fahrenheit']] = df.apply(
    lambda row: pd.Series(
        [celsius_to_fahrenheit(row['City 1']),
         celsius_to_fahrenheit(row['City 2'])]),
         axis=1
)

print(df)

Здесь мы использовали лямбда-выражение, чтобы принимать каждую строку в качестве входных данных, используя axis=1и возвращая объект Series со значениями по Фаренгейту. Эта результирующая серия была назначена столбцам «Город 1 по Фаренгейту» и «Город 2 по Фаренгейту» в DataFrame.

Определите тип возвращаемого значения функции Apply()

Возможно, вы уже заметили, что apply()в наших предыдущих примерах всегда возвращался ряд. Как правило, результатом применения функции является объект Series, который поддерживает структуру индексации исходных данных. Однако мы можем использовать этот result_typeпараметр и установить для него значение «расширить», что указывает на возврат DataFrame. Это особенно полезно, когда нам нужно изменить структуру данных или применить функции, которые генерируют несколько значений.

Давайте изменим наш предыдущий пример, чтобы увидеть, как мы можем вернуть DataFrame, используя result_typeпараметр.

data = {'City 1': [1, 4, 8, 9, 14, 25, 31, 35, 32, 25, 11, 2],
        'City 2': [19, 23, 30, 31, 35, 40, 45, 39, 30, 25, 15, 10]
       }

df = pd.DataFrame(data)

df[['City 1 (Fahrenheit)', 'City 2 (Fahrenheit)']] = df.apply(lambda row: celsius_to_fahrenheit(row), axis=1, result_type='expand')

print(df)

Вывод такой же, как мы получили ранее:

    City 1  City 2  City 1 (Fahrenheit)  City 2 (Fahrenheit)
0        1      19                 33.8                 66.2
1        4      23                 39.2                 73.4
2        8      30                 46.4                 86.0
3        9      31                 48.2                 87.8
4       14      35                 57.2                 95.0
5       25      40                 77.0                104.0
6       31      45                 87.8                113.0
7       35      39                 95.0                102.2
8       32      30                 89.6                 86.0
9       25      25                 77.0                 77.0
10      11      15                 51.8                 59.0
11       2      10                 35.6                 50.0

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

Вопросы производительности

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

Стоит рассмотреть альтернативные подходы, apply() если вам нужна оптимальная производительность для больших наборов данных или задач, требующих больших вычислительных ресурсов. Вы должны использовать встроенные векторизованные операции везде, где это возможно. Например, вы можете использовать sum() метод вместо apply(sum). Вы также можете использовать встроенные строковые операции, такие как str.replace() и условные операции, например, where() для эффективных агрегаций и групповых операций. Кроме того, рассмотрите пакеты Python, такие как Swifter или Dask, которые используют параллельную обработку для эффективной работы с большими наборами данных. В зависимости от размера вашего набора данных и доступных вычислительных ресурсов эти альтернативы могут значительно повысить производительность задач обработки данных по сравнению с использованием apply() в одиночку.

Заключение

Таким образом, apply() функция служит ценным ресурсом для манипулирования данными, особенно в рутинных задачах, требующих повторяющегося кода. Эта функция обеспечивает бесшовную интеграцию пользовательских или встроенных функций с сериями Pandas и DataFrames. Выявление возможностей использования этой apply() функции может значительно повысить вашу производительность при выполнении повседневных задач.