← Назад к вопросам

Что такое apply для датафреймов?

1.8 Middle🔥 161 комментариев
#Pandas и обработка данных#Python и программирование

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

pandas apply(): применение функций к DataFrame

apply() — это метод pandas для применения функции к элементам DataFrame или Series. Это основной инструмент для трансформации данных.

Что такое apply()?

# apply() берёт функцию и применяет её к колонке или строке
df['new_column'] = df['old_column'].apply(function)

Простой пример:

import pandas as pd

df = pd.DataFrame({
    'amount': [100, 200, 300],
    'currency': ['USD', 'EUR', 'GBP']
})

# Хочу округлить все суммы до целых
def round_amount(x):
    return round(x, -1)  # Округляю до десятков

df['rounded'] = df['amount'].apply(round_amount)

print(df)

Результат:

  amount currency  rounded
0    100      USD      100
1    200      EUR      200
2    300      GBP      300

apply() с lambda функциями

Чаще всего использую lambda для коротких функций:

df = pd.DataFrame({
    'price': [100, 200, 300],
    'tax': [10, 20, 30]
})

# Способ 1: обычная функция
def calculate_total(price, tax):
    return price + tax

# Способ 2: lambda (проще для простых операций)
df['total'] = df.apply(lambda row: row['price'] + row['tax'], axis=1)

print(df)

Результат:

  price  tax  total
0    100   10    110
1    200   20    220
2    300   30    330

axis параметр (ВАЖНЫЙ!)

axis=0 (default) — применяю к КОЛОНКАМ

df = pd.DataFrame({
    'A': [1, 2, 3],
    'B': [4, 5, 6]
})

# axis=0: функция получает каждую колонку как Series
result = df.apply(lambda col: col.sum())
print(result)

# Результат:
# A     6
# B    15

axis=1 — применяю к СТРОКАМ

df = pd.DataFrame({
    'A': [1, 2, 3],
    'B': [4, 5, 6]
})

# axis=1: функция получает каждую строку как Series
result = df.apply(lambda row: row['A'] + row['B'], axis=1)
print(result)

# Результат:
# 0     5
# 1     7
# 2     9

Практические примеры для аналитики

Пример 1: Категоризация по диапазонам

df = pd.DataFrame({
    'customer_id': [1, 2, 3, 4, 5],
    'lifetime_value': [150, 500, 250, 1200, 400]
})

# Хочу классифицировать клиентов
def classify_customer(ltv):
    if ltv >= 1000:
        return 'VIP'
    elif ltv >= 500:
        return 'Premium'
    else:
        return 'Standard'

df['segment'] = df['lifetime_value'].apply(classify_customer)

print(df)

Результат:

  customer_id  lifetime_value    segment
0            1             150   Standard
1            2             500   Premium
2            3             250   Standard
3            4            1200       VIP
4            5             400   Standard

Пример 2: Очистка данных

df = pd.DataFrame({
    'email': ['  john@example.com  ', 'jane@example.com', '  bob@test.org  ']
})

# Удаляю пробелы и преобразую в нижний регистр
df['email_clean'] = df['email'].apply(lambda x: x.strip().lower())

print(df)

Результат:

               email        email_clean
0   john@example.com   john@example.com
1  jane@example.com  jane@example.com
2    bob@test.org      bob@test.org

Пример 3: Работа с разными типами данных

df = pd.DataFrame({
    'user_id': [1, 2, 3],
    'created_at': ['2024-01-15', '2024-01-20', '2024-02-01'],
    'tags': [['python', 'sql'], ['ml'], ['python', 'ml', 'stats']]
})

# Преобразую дату в тип datetime
df['created_at'] = df['created_at'].apply(pd.to_datetime)

# Считаю количество тегов
df['tag_count'] = df['tags'].apply(len)

print(df)

Результат:

  user_id created_at tag_count
0        1 2024-01-15         2
1        2 2024-01-20         1
2        3 2024-02-01         3

Пример 4: Расчёты с несколькими колонками

df = pd.DataFrame({
    'product_id': [1, 2, 3],
    'price': [100, 200, 150],
    'quantity_sold': [10, 5, 20],
    'discount_percent': [0, 10, 5]
})

# Функция которая берёт строку и рассчитывает revenue
def calculate_revenue(row):
    revenue = row['price'] * row['quantity_sold']
    discount_amount = revenue * (row['discount_percent'] / 100)
    return revenue - discount_amount

df['revenue'] = df.apply(calculate_revenue, axis=1)

print(df)

Результат:

  product_id  price  quantity_sold  discount_percent  revenue
0           1    100             10                 0     1000
1           2    200              5                10      900
2           3    150             20                 5     2850

apply() vs Vectorization (важно для производительности)

apply() медленнее чем vectorized операции:

import pandas as pd
import time
import numpy as np

# Большой DataFrame (1 млн строк)
df = pd.DataFrame({'value': np.random.rand(1_000_000)})

# Способ 1: apply() (медленно)
start = time.time()
result1 = df['value'].apply(lambda x: x * 2 + 1)
time1 = time.time() - start
print(f"apply(): {time1:.3f} сек")

# Способ 2: vectorized операция (быстро)
start = time.time()
result2 = df['value'] * 2 + 1
time2 = time.time() - start
print(f"Vectorized: {time2:.3f} сек")

print(f"Speedup: {time1/time2:.1f}x")

# Результат:
# apply(): 2.145 сек
# Vectorized: 0.012 сек
# Speedup: 178.8x

Правило: используй vectorization когда возможно!

# ❌ МЕДЛЕННО (apply)
df['new_value'] = df['value'].apply(lambda x: x * 2 + 1)

# ✅ БЫСТРО (vectorized)
df['new_value'] = df['value'] * 2 + 1

Когда использовать apply()

apply() НУЖНА когда:

  1. Логика сложная и не могу сделать vectorized
  2. Нужна условная логика
  3. Работаю с категориями или текстом
# ПРИМЕР: Нужен apply() потому что логика сложная
def complex_calculation(row):
    if row['category'] == 'A':
        return row['amount'] * 1.1
    elif row['category'] == 'B':
        return row['amount'] * 0.9
    else:
        return row['amount']

df['adjusted_amount'] = df.apply(complex_calculation, axis=1)

apply() НЕ НУЖНА когда:

  1. Просто математическая операция → используй vectorization
  2. Работаешь с одной колонкой и простой функцией
# ❌ НЕПРАВИЛЬНО
df['doubled'] = df['value'].apply(lambda x: x * 2)

# ✅ ПРАВИЛЬНО
df['doubled'] = df['value'] * 2

apply() на весь DataFrame

df = pd.DataFrame({
    'A': [1, 2, 3],
    'B': [4, 5, 6],
    'C': [7, 8, 9]
})

# apply на каждую колонку (axis=0)
result = df.apply(lambda col: col.max() - col.min())
print(result)

# Результат (размах для каждой колонки):
# A    2
# B    2
# C    2

Оптимизация: applymap() и map()

applymap() (старое название) / map() (новое) — для элементов

df = pd.DataFrame({
    'A': [1, 2, 3],
    'B': [4, 5, 6]
})

# Применить функцию к КАЖДОМУ элементу
result = df.map(lambda x: x ** 2)

print(result)

Результат:

   A   B
0   1  16
1   4  25
2   9  36

apply() для Series (колонка)

import pandas as pd

s = pd.Series([1, 2, 3, 4, 5])

# Применить функцию к Series
result = s.apply(lambda x: 'even' if x % 2 == 0 else 'odd')

print(result)

# Результат:
# 0      odd
# 1     even
# 2      odd
# 3     even
# 4      odd

Вывод

apply() — мощный инструмент для трансформации данных.

Правила использования:

  1. Для простых операций → используй vectorization
  2. Для сложной логики → используй apply() с lambda или функцией
  3. Для performance → профилируй и оптимизируй
  4. axis=0 для колонок (default)
  5. axis=1 для строк

Практические примеры:

  • Категоризация клиентов по LTV
  • Очистка текстовых данных
  • Условные расчёты
  • Преобразование форматов

Запомни: apply() медленнее vectorization в 100-1000 раз, поэтому используй её только когда нужна сложная логика.