Работа с данными: полное руководство по Pandas
Основные методы обработки данных с Pandas
Наиболее эффективный способ обработки данных включает построение конвейера операций с использованием цепочек методов Pandas. Ниже приведен пример полного цикла обработки набора данных о сотрудниках.
import pandas as pd
# Загрузка данных с указанием типов столбцов
df = pd.read_csv('employees.csv', dtype={'department': 'category', 'salary': 'float64'}, parse_dates=['hire_date'])
# Обработка пропусков: заполнение зарплаты медианой по отделу
df['salary'] = df.groupby('department')['salary'].transform(lambda x: x.fillna(x.median()))
# Фильтрация: оставить только активных сотрудников (есть столбец status)
df = df[df['status'] == 'Active'].copy()
# Добавление столбца с возрастной группой
def age_group(age):
if age < 30: return 'Young'
elif age < 50: return 'Middle'
else: return 'Senior'
df['age_group'] = df['age'].apply(age_group)
# Группировка и агрегация: средняя зарплата и количество по отделу и возрастной группе
result = df.groupby(['department', 'age_group']).agg(avg_salary=('salary', 'mean'), count=('employee_id', 'count'))
# Сортировка
result = result.sort_values(['department', 'avg_salary'], ascending=[True, False])
# Сохранение
result.to_csv('processed_employees.csv')обработка больших данных python (обработка больших данных в python)
В этом конвейере каждый шаг использует векторизованные операции, что обеспечивает высокую производительность. Важно создавать копию датафрейма после фильтрации, чтобы избежать предупреждений SettingWithCopyWarning.
Типичные проблемы и их решения:
- SettingWithCopyWarning - возникает при изменении среза датафрейма. Решение: использовать
.copy()после фильтрации или применять.loc. - Проблемы с типами данных - если столбец объявлен как
object, операции могут быть медленнее. Рекомендуется явно указывать типы при загрузке. - Использование inplace -
inplace=Trueизменяет исходный объект и может привести к цепочке неожиданных изменений. Лучше присваивать результат новой переменной.
Как обработать пропуски с использованием разных стратегий?
Помимо группового заполнения медианой, существуют другие методы: простое удаление строк с пропусками, заполнение константой, прямая/обратная интерполяция.
# Удаление строк хотя бы с одним пропуском
df_clean = df.dropna()
# Заполнение всех пропусков нулями
df_filled = df.fillna(0)
# Заполнение пропусков предыдущим значением (ffill) или следующим (bfill)
df_ffill = df.fillna(method='ffill')
df_bfill = df.fillna(method='bfill')
# Линейная интерполяция (только для числовых столбцов)
df_interp = df.interpolate(method='linear')очистка данных python (очистка данных в python)
Выбор стратегии зависит от природы данных и бизнес-требований. Например, для временных рядов часто используют интерполяцию или ffill.
Возможные проблемы:
- Удаление строк приводит к потере информации. Если пропусков много, результат может быть нерепрезентативным.
- Интерполяция предполагает линейную зависимость между соседними точками, что не всегда корректно.
- При использовании
fillna(method='ffill')начальные пропуски останутся; требуется комбинировать сbfill.
Как выполнить группировку и агрегацию без использования groupby?
Для некоторых сценариев (например, построение сводных таблиц) удобнее применять pivot_table или crosstab.
# Сводная таблица: средняя зарплата по отделам и возрастным группам
pivot = pd.pivot_table(df, values='salary', index='department', columns='age_group', aggfunc='mean')
# Перекрестная таблица частот
cross = pd.crosstab(df['department'], df['age_group'])
# Агрегация с несколькими функциями через pivot_table
pivot_multi = pd.pivot_table(df, values='salary', index='department', aggfunc=['mean', 'sum', 'count'])
Python подготовка данных (подготовка данных в python)
pivot_table автоматически обрабатывает мультииндексы и может заменять несколько вызовов groupby.
Частые ошибки:
- При отсутствии комбинаций в данных создаются пропуски (NaN). Их можно заполнить через
fill_value. - Неверный выбор
aggfunc- если передать список, результат будет иметь MultiIndex столбцов, что усложняет дальнейшую обработку.
Как объединить несколько таблиц с разными ключами?
Pandas предоставляет merge, join и concat для различных сценариев слияния.
# Соединение по ключу (внутреннее)
merged = pd.merge(df_employees, df_salaries, on='employee_id', how='inner')
# Левое внешнее соединение
merged_left = pd.merge(df_employees, df_departments, on='dept_id', how='left')
# Соединение по индексу (join)
df_emp.set_index('id').join(df_info.set_index('id'), how='outer')
# Конкатенация строк (добавление новых записей)
combined = pd.concat([df_2023, df_2024], ignore_index=True)Выбор типа соединения зависит от того, какие строки должны остаться в результате.
Проблемы при объединении:
- Несовпадение типов ключей (например, int vs string) - приводит к пустому результату. Необходимо привести ключи к общему типу.
- Дубликаты ключей - при наличии нескольких записей с одинаковым ключом результирующая таблица содержит декартово произведение. Фильтр перед объединением.
- При конкатенации с разными столбцами появляются NaN. Можно использовать
join='inner'или удалить потом.
Продвинутые примеры обработки данных
Применение пользовательской функции к строкам
С помощью apply можно применить сложную логику, затрагивающую несколько столбцов.
import pandas as pd
import numpy as np
df = pd.DataFrame({'product': ['A', 'B', 'C'],
'price': [100, 200, 150],
'quantity': [3, 5, 2]})
def calculate(row):
total = row['price'] * row['quantity']
if total > 500:
discount = 0.1
else:
discount = 0.0
return pd.Series([total, discount], index=['total', 'discount'])
result = df.apply(calculate, axis=1)
df = pd.concat([df, result], axis=1)product price quantity total discount 0 A 100 3 300 0.0 1 B 200 5 1000 0.1 2 C 150 2 300 0.0
Работа с датами: извлечение компонентов и фильтрация
Библиотека Pandas предоставляет удобный доступ к компонентам даты через .dt аксессор.
df = pd.DataFrame({'date': pd.date_range('2023-01-01', periods=10, freq='M'),
'sales': np.random.randint(100, 200, 10)})
df['year'] = df['date'].dt.year
df['quarter'] = df['date'].dt.quarter
df['month_name'] = df['date'].dt.month_name()
q1 = df[df['quarter'] == 1]date sales year quarter month_name 0 2023-01-31 136 2023 1 January 1 2023-02-28 137 2023 1 February 2 2023-03-31 184 2023 1 March
Оконные функции: скользящее среднее и кумулятивная сумма
Оконные вычисления полезны для анализа временных рядов.
df = pd.DataFrame({'value': [1, 3, 5, 7, 9, 11]})
df['rolling_mean_3'] = df['value'].rolling(window=3).mean()
df['cumsum'] = df['value'].cumsum()value rolling_mean_3 cumsum 0 1 NaN 1 1 3 NaN 4 2 5 3.000000 9 3 7 5.000000 16 4 9 7.000000 25 5 11 9.000000 36
Использование категориального типа для экономии памяти
Категориальный тип оптимизирует хранение строковых столбцов с небольшим количеством уникальных значений.
df = pd.DataFrame({'category': ['A', 'B', 'A', 'C', 'B', 'A']})
df['category'] = df['category'].astype('category')
print(df.dtypes)
print(df['category'].cat.codes)category category dtype: object 0 0 1 1 2 0 3 2 4 1 5 0 dtype: int8
Производительные фильтрации с query и eval
query и eval позволяют выполнять операции быстрее за счет использования оптимизированных внутренних выражений.
df = pd.DataFrame({'a': range(10), 'b': range(10, 20)})
filtered = df.query('a > 3 and b < 15')
df['c'] = df.eval('a + b * 2')a b c 0 0 10 20 1 1 11 23 2 2 12 26 3 3 13 29 4 4 14 32 5 5 15 35
Обработка больших данных с чанками и сохранение в Parquet
Для работы с файлами, не помещающимися в память, используется построчное чтение (chunks). Формат Parquet обеспечивает высокую скорость записи и сжатие.
import pandas as pd
chunksize = 10000
chunks = []
for chunk in pd.read_csv('large.csv', chunksize=chunksize):
processed = chunk[chunk['value'] > 0]
chunks.append(processed)
result = pd.concat(chunks)
result.to_parquet('processed.parquet', index=False)