Работа с данными: полное руководство по Pandas

Раздел: Python -> 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' или удалить потом.
- структурированные данные python (структурированные данные в python)
- генерация данных python (генерация данных в python)
- Python код символа (код символа в python)

Продвинутые примеры обработки данных

Применение пользовательской функции к строкам

С помощью 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)

Обработка данных на Python - comments

En
обработка данных на python (python)