Обработка данных с помощью Pandas: основы и продвинутые техники

Раздел: Обработка данных -> Библиотека Pandas

Основные возможности Pandas

Библиотека Pandas предоставляет мощные инструменты для работы с табличными данными. Её ключевые структуры: Series (одномерный массив) и DataFrame (двумерная таблица). Ниже рассматриваются типичные операции с пояснением выбора наиболее эффективного подхода и альтернатив.

Как создать DataFrame из словаря?

Наиболее прямой способ - передать словарь, где ключи становятся названиями столбцов, а значения - списками одинаковой длины.

import pandas as pd
data = {'Имя': ['Анна', 'Борис', 'Виктор'],
        'Возраст': [25, 30, 35],
        'Город': ['Москва', 'СПб', 'Казань']}
df = pd.DataFrame(data)
print(df)

Python pandas index (работа с индексом dataframe в pandas)

      Имя  Возраст  Город
0    Анна       25  Москва
1   Борис       30    СПб
2  Виктор       35  Казань

работа с библиотекой pandas python (работа с библиотекой pandas в python)

Этот метод интуитивно понятен и подходит для небольших объёмов данных.

Как создать DataFrame из списка списков?

Если данные представлены построчно, используют список списков с указанием названий столбцов.

rows = [['Анна', 25, 'Москва'], ['Борис', 30, 'СПб']]
df2 = pd.DataFrame(rows, columns=['Имя', 'Возраст', 'Город'])
print(df2)

Python pandas работа с данными (работа с данными в pandas)

Такой подход удобен при чтении данных из внешних источников, где строки уже сформированы.

Проблема: несовпадение длины списков в словаре вызывает ошибку ValueError. Решение - проверить, что все списки одинаковой длины, или использовать pd.DataFrame.from_dict с параметром orient='index'.

Как загрузить данные из CSV файла?

Основная функция - pd.read_csv(). Она автоматически определяет разделитель, типы столбцов и создаёт DataFrame.

df_csv = pd.read_csv('data.csv', encoding='utf-8', sep=',')
print(df_csv.head())

Параметр encoding важен для корректного отображения кириллицы. Если файл содержит заголовки, они становятся именами столбцов.

Как загрузить данные из Excel?

Для файлов .xlsx используют pd.read_excel(), указав имя листа.

df_excel = pd.read_excel('report.xlsx', sheet_name='Лист1')
print(df_excel.info())

Перед использованием установите библиотеку openpyxl или xlrd.

Типичная ошибка: FileNotFoundError - файл не найден. Решение - указать полный путь или проверить рабочую директорию (os.getcwd()). Для CSV с разделителем-табуляцией нужно указывать sep=' '.

Как выбрать строки по меткам (loc) и по позициям (iloc)?

loc использует метки индекса, iloc - целочисленные позиции. Пример:

# loc - по меткам
df_sub = df.loc[1:2, ['Имя', 'Возраст']]
# iloc - по позициям (все строки, столбцы 0 и 1)
df_sub2 = df.iloc[:, 0:2]

Базовый способ фильтрации - булево индексирование.

Как отфильтровать строки по условию?

Условие записывается внутри квадратных скобок. Например, выбрать всех старше 25 лет:

df_old = df[df['Возраст'] > 25]

Альтернатива - метод query() для сложных условий:

df_old_q = df.query('Возраст > 25 and Город == "Москва"')

Метод query() читается лучше при множественных условиях.

Ошибка: использование df[df['Возраст'] > 25] без скобок вокруг условия - синтаксически верно, но если условие многострочное, лучше сохранить его в переменную. Для query() кавычки внутри строки экранировать.

Как обработать пропущенные значения?

Пропуски обозначаются как NaN. Основные приёмы: удаление строк с NaN (dropna()) или заполнение (fillna()). Наиболее универсально - заполнение средним или медианным значением.

# Заполнение средним
mean_val = df['Возраст'].mean()
df['Возраст'] = df['Возраст'].fillna(mean_val)
# Удаление всех строк с любым NaN
df_clean = df.dropna()

Как заменить пропуски на предыдущее значение?

Для временных рядов часто используют method='ffill' (forward fill).

df['temp'].fillna(method='ffill', inplace=True)

Метод bfill заполняет следующим значением.

Проблема: inplace=True изменяет исходный объект; рекомендуется присваивать результат новому DataFrame для отслеживания шагов. Метод fillna с method не всегда подходит для категориальных данных.

Как сгруппировать данные и вычислить статистики?

Метод groupby() в сочетании с агрегацией - основа анализа.

grouped = df.groupby('Город')['Возраст'].mean()
print(grouped)

Результат - Series с группами в индексе. Для нескольких агрегаций используют agg().

Как применить несколько функций к разным столбцам?

Словарь с функциями для каждого столбца:

agg_dict = {'Возраст': ['mean', 'max'], 'Зарплата': 'sum'}
df_agg = df.groupby('Город').agg(agg_dict)

Это даёт MultiIndex в столбцах.

Ошибка: если в группировке указать столбец с пропусками, они исключаются из группы. Для сохранения используют dropna=False.

Как объединить два DataFrame по ключу?

SQL-подобное слияние через merge() с указанием ключа и типа соединения.

df_left = pd.DataFrame({'id': [1,2], 'name': ['A','B']})
df_right = pd.DataFrame({'id': [1,3], 'salary': [500,700]})
merged = pd.merge(df_left, df_right, on='id', how='left')
print(merged)
   id name  salary
0   1    A   500.0
1   2    B     NaN

Параметр how определяет тип: inner, left, right, outer.

Как объединить строки по оси (stack)?

Функция concat() добавляет строки или столбцы.

df_new = pd.concat([df1, df2], ignore_index=True)

Если индексы не пересекаются, ignore_index=True переиндексирует.

Проблема: при merge если ключи не уникальны, строки размножаются. Проверяйте дубликаты через duplicated().

Как применить пользовательскую функцию к столбцу или строке?

Метод apply() позволяет выполнить произвольную обработку.

def age_group(age):
    if age < 30:
        return 'young'
    else:
        return 'old'
df['Группа'] = df['Возраст'].apply(age_group)

Для всей строки используйте axis=1.

Как заменить значения по словарю?

Метод map() применяется к Series.

city_map = {'Москва': 'MOW', 'СПб': 'LED'}
df['Код'] = df['Город'].map(city_map)

Если ключа нет, результат - NaN.

Ошибка: apply может быть медленным на больших DataFrame; для векторных операций предпочтительны встроенные методы Pandas и NumPy.

Как работать с датами?

Pandas умеет парсить строки с датами через pd.to_datetime().

dates = ['2024-01-15', '2025-03-20']
df['Дата'] = pd.to_datetime(dates)
df['Год'] = df['Дата'].dt.year
print(df)

После преобразования доступны атрибуты .dt (year, month, day, weekday и т.д.).

Как отфильтровать строки по диапазону дат?

Используйте булево условие с операторами сравнения.

start = pd.to_datetime('2024-01-01')
end = pd.to_datetime('2024-12-31')
mask = (df['Дата'] >= start) & (df['Дата'] <= end)
df_range = df[mask]

Метод between() упрощает:

df_range = df[df['Дата'].between(start, end)]
Проблема: неправильный формат даты вызывает ошибку. Используйте параметр format в to_datetime для нестандартных строк.

Продвинутые примеры работы с Pandas

Ниже представлены расширенные сценарии, демонстрирующие комбинирование возможностей библиотеки.

Пример 1. Сводные таблицы (pivot table)

Создадим сводную таблицу, где строки - города, столбцы - возрастные группы, значения - средняя зарплата.

Пример
import pandas as pd
import numpy as np
data = {
    'Город': ['Москва', 'Москва', 'СПб', 'СПб', 'Казань'],
    'Возраст': [25, 35, 30, 40, 28],
    'Зарплата': [100000, 150000, 80000, 120000, 90000]
}
df = pd.DataFrame(data)
df['Возрастная_группа'] = pd.cut(df['Возраст'], bins=[0, 30, 40, 100], labels=['молодой', 'средний', 'старший'])
pivot = pd.pivot_table(df, values='Зарплата', index='Город', columns='Возрастная_группа', aggfunc=np.mean, fill_value=0)
print(pivot)
Возрастная_группа  молодой  средний  старший
Город                                      
Казань                90000        0        0
Москва               100000   150000        0
СПб                   80000   120000        0

Функция pd.cut() разбивает возраст на интервалы. Параметр fill_value=0 заменяет NaN на 0.

Пример 2. Объединение с разными ключами и переименование столбцов

Покажем слияние двух DataFrame с разными названиями ключевых столбцов.

Пример
orders = pd.DataFrame({
    'order_id': [1,2,3],
    'customer_id': [101,102,101],
    'amount': [250, 300, 150]
})
customers = pd.DataFrame({
    'cust_id': [101,102,103],
    'name': ['Анна', 'Борис', 'Виктор']
})
# Слияние с указанием left_on и right_on
merged = pd.merge(orders, customers, left_on='customer_id', right_on='cust_id', how='left')
merged = merged.drop('cust_id', axis=1)  # удаляем дублирующийся столбец
print(merged)
   order_id  customer_id  amount   name
0         1          101     250   Анна
1         2          102     300  Борис
2         3          101     150   Анна

После слияния столбец-ключ из правого DataFrame (cust_id) удалён. Если требуется сохранить оба, используется параметр suffixes.

Пример 3. Оконные функции: скользящее среднее

Для временного ряда вычислим скользящее среднее с окном 3.

Пример
dates = pd.date_range('2025-01-01', periods=10, freq='D')
values = [10, 12, 15, 14, 18, 20, 22, 25, 24, 30]
df_ts = pd.DataFrame({'date': dates, 'value': values})
df_ts['rolling_mean'] = df_ts['value'].rolling(window=3).mean()
print(df_ts)
        date  value  rolling_mean
0 2025-01-01     10           NaN
1 2025-01-02     12           NaN
2 2025-01-03     15     12.333333
3 2025-01-04     14     13.666667
4 2025-01-05     18     15.666667
5 2025-01-06     20     17.333333
6 2025-01-07     22     20.000000
7 2025-01-08     25     22.333333
8 2025-01-09     24     23.666667
9 2025-01-10     30     26.333333

Первые два значения NaN, так как окно 3 не заполнено полностью. Метод rolling() поддерживает различные функции: sum, std, apply и т.д.

Пример 4. Применение функции к нескольким столбцам с помощьюapply

Допустим, нужно нормализовать несколько числовых столбцов (вычесть среднее и разделить на стандартное отклонение).

Пример
df_norm = pd.DataFrame({
    'A': [10, 20, 30],
    'B': [100, 200, 300],
    'C': [5, 15, 25]
})
def normalize_col(col):
    return (col - col.mean()) / col.std()
df_norm_scaled = df_norm.apply(normalize_col)
print(df_norm_scaled)
          A         B         C
0 -1.224745 -1.224745 -1.224745
1  0.000000  0.000000  0.000000
2  1.224745  1.224745  1.224745

Функция применяется к каждому столбцу (axis=0 по умолчанию). Для построчной нормализации используйте axis=1.

Пример 5. Обработка дубликатов с выбором строки для сохранения

В данных могут быть дубликаты по одному столбцу; нужно оставить запись с наибольшим значением в другом столбце.

Пример
df_dup = pd.DataFrame({
    'id': [1,1,2,2],
    'version': [1,2,1,3],
    'value': [100, 150, 200, 180]
})
# Сортируем по id и version по убыванию, затем удаляем дубликаты, оставляя первый (последняя версия)
df_sorted = df_dup.sort_values(['id', 'version'], ascending=[True, False])
df_final = df_sorted.drop_duplicates(subset='id', keep='first')
print(df_final)
   id  version  value
1   1        2    150
3   2        3    180

Параметр keep='first' оставляет первое вхождение после сортировки. Альтернативно можно использовать groupby().nth() или idxmax().

Работа с библиотекой Pandas в Python - comments

En
работа с библиотекой pandas python (python)