Обработка информации в Pandas: от загрузки до продвинутого анализа
Основные методы обработки данных в Pandas
Библиотека Pandas предоставляет мощные инструменты для манипуляции табличными данными. В этой части рассматриваются ключевые подходы к преобразованию, фильтрации и агрегации данных. Каждый подход сопровождается вопросом, на который он отвечает, и разбором типичных трудностей.
Как эффективно применить функцию к каждому элементу столбца и создать новый столбец на основе расчётов?
Наиболее эффективное решение заключается в использовании векторизованных методов .map(), .apply() и встроенных операций Pandas. Эти методы работают на уровне Cython, что обеспечивает высокую скорость. Рассмотрим пример обработки данных о продажах:
import pandas as pd
import numpy as np
# Исходные данные
df = pd.DataFrame({
'product': ['A', 'B', 'C', 'A', 'B'],
'price': [100, np.nan, 150, 120, 110],
'quantity': [2, 5, 3, 1, 4]
})
print(df)обработка больших данных python (обработка больших данных в python)
product price quantity 0 A 100.0 2 1 B NaN 5 2 C 150.0 3 3 A 120.0 1 4 B 110.0 4
очистка данных python (очистка данных в python)
Пояснение шагов:
- Заполнение пропусков медианным значением с помощью .fillna():
df['price'] = df['price'].fillna(df['price'].median()) - Создание столбца 'total' через векторное умножение:
df['total'] = df['price'] * df['quantity'] - Применение пользовательской функции к столбцу 'product' с .map():
df['category'] = df['product'].map({'A': 'food', 'B': 'drink', 'C': 'other'}) - Фильтрация строк по условию:
filtered = df[df['total'] > 300]
df['price'] = df['price'].fillna(df['price'].median())
df['total'] = df['price'] * df['quantity']
df['category'] = df['product'].map({'A': 'food', 'B': 'drink', 'C': 'other'})
filtered = df[df['total'] > 300]
print(filtered)
Python подготовка данных (подготовка данных в python)
product price quantity total category 2 C 150.0 3 450.0 other
Python работа с большими данными (работа с большими данными в python)
Типичные ошибки:
- SettingWithCopyWarning при попытке изменить срез датафрейма. Используйте .copy() для создания явной копии.
- При использовании .apply() без векторизации производительность падает на больших датафреймах. Применяйте встроенные методы.
- Забыли обработать пропуски перед арифметическими операциями.
Как обработать строки датафрейма с помощью цикла for?
Иногда требуется итерация по строкам, например, для сложной логики, которую сложно векторизовать. Используется .iterrows() или .itertuples().
for index, row in df.iterrows():
if row['product'] == 'A':
df.loc[index, 'flag'] = 'premium'
print(df)структурированные данные python (структурированные данные в python)
product price quantity total category flag 0 A 100.0 2 200.0 food premium 1 B 105.0 5 525.0 drink NaN 2 C 150.0 3 450.0 other NaN 3 A 120.0 1 120.0 food premium 4 B 110.0 4 440.0 drink NaN
генерация данных python (генерация данных в python)
Проблемы:
- Очень медленная работа на больших данных (O(n) с накладными расходами на каждый вызов).
- Изменение датафрейма внутри цикла может привести к непредсказуемым результатам, если не использовать .loc.
- Рекомендуется переписать логику на векторизованные операции.
Как создать новый столбец с помощью генератора списков (list comprehension)?
Генераторы списков быстрее циклов for, но медленнее векторизованных методов. Подходит для простых преобразований.
df['discount'] = [0.1 if p > 100 else 0.05 for p in df['price']]
print(df)Python код символа (код символа в python)
product price quantity total category discount 0 A 100.0 2 200.0 food 0.05 1 B 105.0 5 525.0 drink 0.10 2 C 150.0 3 450.0 other 0.10 3 A 120.0 1 120.0 food 0.10 4 B 110.0 4 440.0 drink 0.10
код из файла python (код из файла python)
Ошибки:
- Необходимость обращаться к столбцам через .values или .tolist() для ускорения.
- При работе с пропусками генератор может выдать ошибку, если не обработаны NaN.
Как быстро преобразовать текстовые данные в столбце?
Для строковых манипуляций Pandas предоставляет .str аксессор, позволяющий применять методы регулярных выражений, разбиение, замену.
df['product_code'] = ['A-123', 'B-456', 'C-789', 'A-101', 'B-202']
df['category_letter'] = df['product_code'].str[0]
df['number'] = df['product_code'].str.split('-').str[1].astype(int)
print(df[['product_code', 'category_letter', 'number']])обработка данных на python (обработка данных на python)
product_code category_letter number 0 A-123 A 123 1 B-456 B 456 2 C-789 C 789 3 A-101 A 101 4 B-202 B 202
Частые проблемы:
- Игнорирование пропусков: если в столбце есть NaN, методы .str вернут NaN.
- Использование регулярных выражений без экранирования спецсимволов.
Расширенные примеры обработки данных
В этом разделе представлены более сложные сценарии, часто встречающиеся на практике: работа с временными рядами, многомерная агрегация, объединение таблиц и скользящие вычисления. Каждый пример содержит код и ожидаемый вывод.
1. Обработка временных рядов
Преобразование строковой колонки с датами в тип datetime, создание признаков и фильтрация по периоду.
import pandas as pd
# Данные с датами
sales = pd.DataFrame({
'date': ['2024-01-05', '2024-02-10', '2024-03-15', '2024-01-20'],
'amount': [200, 150, 300, 250]
})
sales['date'] = pd.to_datetime(sales['date'])
sales['year'] = sales['date'].dt.year
sales['month'] = sales['date'].dt.month
sales['day_of_week'] = sales['date'].dt.day_name()
# Фильтр: только февраль
feb_sales = sales[sales['date'].dt.month == 2]
print(feb_sales)date amount year month day_of_week 1 2024-02-10 150 2024 2 Saturday
2. Группировка с несколькими агрегациями и пользовательской функцией
Группировка по продукту, вычисление суммы, среднего, а также размаха (max - min) с помощью .agg().
# используем df из предыдущего примера
grouped = df.groupby('product').agg(
total_quantity=('quantity', 'sum'),
avg_price=('price', 'mean'),
price_range=('price', lambda x: x.max() - x.min())
).reset_index()
print(grouped)product total_quantity avg_price price_range 0 A 3 110.0 20.0 1 B 9 107.5 5.0 2 C 3 150.0 0.0
3. Объединение таблиц (merge) с разными типами соединений
Рассмотрим две таблицы: заказы и информация о покупателях. Выполним inner, left и outer merge, обрабатывая дубликаты.
orders = pd.DataFrame({
'order_id': [1,2,3,4],
'customer_id': [101,102,101,103],
'amount': [250, 180, 300, 220]
})
customers = pd.DataFrame({
'customer_id': [101,102,104],
'name': ['Alice', 'Bob', 'Charlie']
})
# inner merge
inner = pd.merge(orders, customers, on='customer_id', how='inner')
print('Inner merge:')
print(inner)
# left merge с сохранением всех заказов
left = pd.merge(orders, customers, on='customer_id', how='left')
print('\nLeft merge:')
print(left)Inner merge: order_id customer_id amount name 0 1 101 250 Alice 1 3 101 300 Alice 2 2 102 180 Bob Left merge: order_id customer_id amount name 0 1 101 250 Alice 1 2 102 180 Bob 2 3 101 300 Alice 3 4 103 220 NaN
Важно: при наличии дубликатов ключей в одной из таблиц merge создаст декартово произведение. Перед merge рекомендуется проверять уникальность ключей или использовать параметр validate.
4. Сводные таблицы с pivot_table
Создание многомерной агрегации с возможностью заполнения пропусков.
# данные о продажах по регионам и продуктам
df_sales = pd.DataFrame({
'region': ['North', 'South', 'North', 'West', 'South', 'West'],
'product': ['A', 'A', 'B', 'A', 'B', 'B'],
'sales': [100, 200, 150, 300, 250, 180]
})
pivot = df_sales.pivot_table(
index='region',
columns='product',
values='sales',
aggfunc='sum',
fill_value=0
).reset_index()
print(pivot)product region A B 0 North 100 150 1 South 200 250 2 West 300 180
5. Скользящие вычисления (rolling и expanding)
Расчет скользящего среднего и кумулятивной суммы для временных рядов.
time_series = pd.DataFrame({
'day': pd.date_range('2024-01-01', periods=7),
'value': [10, 20, 15, 25, 30, 35, 40]
}).set_index('day')
time_series['rolling_mean_3'] = time_series['value'].rolling(window=3).mean()
time_series['cumulative_sum'] = time_series['value'].expanding().sum()
print(time_series)value rolling_mean_3 cumulative_sum day 2024-01-01 10 NaN 10 2024-01-02 20 NaN 30 2024-01-03 15 15.000000 45 2024-01-04 25 20.000000 70 2024-01-05 30 23.333333 100 2024-01-06 35 30.000000 135 2024-01-07 40 35.000000 175
Обратите внимание: первые строки скользящего среднего содержат NaN, если окно не заполнено.