Что такое apply для датафреймов?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
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() НУЖНА когда:
- Логика сложная и не могу сделать vectorized
- Нужна условная логика
- Работаю с категориями или текстом
# ПРИМЕР: Нужен 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() НЕ НУЖНА когда:
- Просто математическая операция → используй vectorization
- Работаешь с одной колонкой и простой функцией
# ❌ НЕПРАВИЛЬНО
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() — мощный инструмент для трансформации данных.
Правила использования:
- Для простых операций → используй vectorization
- Для сложной логики → используй apply() с lambda или функцией
- Для performance → профилируй и оптимизируй
- axis=0 для колонок (default)
- axis=1 для строк
Практические примеры:
- Категоризация клиентов по LTV
- Очистка текстовых данных
- Условные расчёты
- Преобразование форматов
Запомни: apply() медленнее vectorization в 100-1000 раз, поэтому используй её только когда нужна сложная логика.