Pandas: библиотека анализа данных в Python

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

Библиотека Pandas предоставляет мощные инструменты для работы с табличными данными в Python. Её основные структуры - Series (одномерный массив) и DataFrame (двумерная таблица). В этой статье рассмотрены ключевые операции, альтернативные подходы и типичные ошибки.

Основные операции с библиотекой Pandas

Как создать DataFrame из различных источников?

Стандартный способ: из словаря списков

import pandas as pd
df = pd.DataFrame({'Name': ['Alice', 'Bob'], 'Age': [25, 30]})
print(df)

библиотека numpy python (библиотека numpy для python)

    Name  Age
0  Alice   25
1    Bob   30

библиотека pandas python (библиотека pandas для python)

Ключи словаря становятся названиями столбцов, значения - данными. Этот метод интуитивно понятен и подходит для небольших наборов.

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

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

Функция read_csv - основной способ чтения табличных файлов. Параметр encoding помогает избежать ошибок с кодировкой (например, 'cp1251' для русских текстов).

Как создать DataFrame из списка словарей?

data = [{'Name': 'Alice', 'Age': 25}, {'Name': 'Bob', 'Age': 30}]
df = pd.DataFrame(data)

Каждый элемент списка - строка. Удобно при получении данных из API.

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

data = [['Alice', 25], ['Bob', 30]]
df = pd.DataFrame(data, columns=['Name', 'Age'])

Необходимо явно указать названия столбцов.

Проблема: Если списки разной длины или типы данных в столбце смешаны, Pandas может создать столбец с типом object, что замедляет операции. Решение: привести типы после создания (например, df['Age'] = df['Age'].astype(int)).

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

Булево индексирование

filtered = df[df['Age'] > 25]
print(filtered)

Выражение df['Age'] > 25 возвращает булев массив, который используется для фильтрации строк. Простой и производительный способ.

Как использовать метод query?

filtered = df.query('Age > 25')
print(filtered)

query позволяет писать условие строкой, что удобно при динамических фильтрах и улучшает читаемость.

Как получить доступ по позициям или меткам?

# По меткам
print(df.loc[0:1, ['Name']])
# По позициям
print(df.iloc[0:2, 0])

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

Проблема: Цепочки операций вида df[df['col'] > 0]['other_col'] вызывают SettingWithCopyWarning. Решение: использовать .loc['row', 'col'] для явного указания и избегать цепочек.

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

Удаление строк с пропусками

df_clean = df.dropna()

По умолчанию удаляются строки, содержащие хотя бы одно значение NaN. Параметр how='all' удаляет только строки, полностью состоящие из NaN.

Замена пропусков константой

df_filled = df.fillna(0)

Заменит все NaN на 0.

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

df_ffill = df.fillna(method='ffill')
df_bfill = df.fillna(method='bfill')

Метод 'ffill' переносит последнее ненулевое значение вниз, 'bfill' - наоборот. Полезно для временных рядов.

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

df_interp = df.interpolate()

Interpolate применяет линейную интерполяцию между известными точками.

Проблема: Использование inplace=True (например, df.dropna(inplace=True)) может привести к неожиданным побочным эффектам. Решение: предпочитать возврат нового объекта (без inplace).

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

Простая агрегация по одному столбцу

grouped = df.groupby('Category')['Value'].mean()
print(grouped)

Среднее значение для каждой категории.

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

grouped = df.groupby('Category')['Value'].agg(['mean', 'sum', 'count'])

agg принимает список или словарь для разных столбцов.

Как выполнить трансформацию с сохранением исходной формы?

df['Mean_by_cat'] = df.groupby('Category')['Value'].transform('mean')

transform возвращает Series той же длины, что и исходный DataFrame.

Проблема: После groupby индекс становится мультииндексом. Решение: использовать as_index=False или reset_index() для возврата обычного индекса.

Как объединить несколько DataFrame?

Объединение по ключу с помощью merge

merged = pd.merge(df1, df2, on='key', how='inner')
print(merged)

Работает аналогично SQL JOIN. how может быть 'inner', 'outer', 'left', 'right'.

Как сложить таблицы по строкам или столбцам?

concat_rows = pd.concat([df1, df2], axis=0)
concat_cols = pd.concat([df1, df2], axis=1)

concat просто склеивает таблицы, игнорируя индексы. Для выравнивания по индексу используйте join='inner' или join='outer'.

Как объединить по индексу?

joined = df1.join(df2, how='left')

join - удобный метод для объединения по индексу, эквивалентен merge(left_index=True, right_index=True).

Проблема: Дублирование столбцов с одинаковым именем (например, 'key_x' и 'key_y'). Решение: задать суффиксы через параметр suffixes=('_left', '_right') или заранее переименовать столбцы.

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

Преобразование строк в datetime

df['date'] = pd.to_datetime(df['date'])

Pandas автоматически парсит большинство распространённых форматов. Для явного указания используйте format='%Y-%m-%d'.

Как извлечь компоненты даты?

df['year'] = df['date'].dt.year
df['month'] = df['date'].dt.month

Атрибут .dt предоставляет доступ к компонентам (год, месяц, день, день недели и т.д.).

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

daily = df.set_index('date').resample('D').mean()

resample позволяет перейти к другой частоте (например, 'D' - день, 'M' - месяц) и применить агрегацию.

Проблема: Неправильное распознавание формата даты (например, '01-02-2020' как 1 февраля вместо 2 января). Решение: задать dayfirst=True или явно указать format.

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

В этом разделе приведены менее распространённые, но полезные техники, расширяющие возможности анализа данных.

Мультииндекс (MultiIndex)

Мультииндекс позволяет работать с иерархическими данными.

Пример
arrays = [['A', 'A', 'B', 'B'], [1, 2, 1, 2]]
index = pd.MultiIndex.from_arrays(arrays, names=['letter', 'number'])
df = pd.DataFrame({'value': [10, 20, 30, 40]}, index=index)
print(df)
              value
letter number       
A      1          10
       2          20
B      1          30
       2          40

Можно выбирать данные по частичному индексу:

Пример
print(df.loc['A'])
        value
number       
1          10
2          20

Применение функций через apply

Метод apply позволяет применить пользовательскую функцию к каждой строке или столбцу.

Пример
df = pd.DataFrame({'a': [1, 2, 3], 'b': [4, 5, 6]})
def row_sum(row):
    return row['a'] + row['b']
df['sum'] = df.apply(row_sum, axis=1)
print(df)
   a  b  sum
0  1  4    5
1  2  5    7
2  3  6    9

Для простых операций лучше использовать векторизованные выражения, но apply даёт гибкость.

Оптимизация памяти с категориальным типом

Если столбец содержит повторяющиеся строки, преобразование в category экономит память.

Пример
df = pd.DataFrame({'city': ['Moscow', 'SPb', 'Moscow', 'Kazan']})
df['city'] = df['city'].astype('category')
print(df.dtypes)
print(df.memory_usage(deep=True))
city    category
dtype: object
Index        128
city         168

Для больших данных разница становится значительной.

Обработка больших файлов по частям

Использование chunksize при чтении позволяет обработать файл, не загружая его целиком в память.

Пример
chunks = pd.read_csv('large.csv', chunksize=10000)
result = []
for chunk in chunks:
    # фильтрация каждой части
    filtered = chunk[chunk['value'] > 0]
    result.append(filtered)
df_final = pd.concat(result)
print(df_final.shape)

Такой подход эффективен для файлов, размер которых превышает доступную RAM.

Переформатирование таблиц: pivot и melt

pivot превращает длинную таблицу в широкую, melt - наоборот.

Пример
df_long = pd.DataFrame({
    'year': [2020, 2020, 2021, 2021],
    'type': ['sales', 'profit', 'sales', 'profit'],
    'value': [100, 20, 150, 30]
})
df_wide = df_long.pivot(index='year', columns='type', values='value')
print(df_wide)
# обратно
df_melted = df_wide.melt(id_vars=['year'], var_name='type', value_name='value')
print(df_melted)
type    profit  sales
year                
2020       20    100
2021       30    150
   year    type  value
0  2020  profit     20
1  2021  profit     30
2  2020   sales    100
3  2021   sales    150

Скользящие окна (rolling) и расширяющиеся окна (expanding)

Позволяют вычислять статистики с учётом окна данных.

Пример
df = pd.DataFrame({'value': [1, 2, 3, 4, 5]})
df['rolling_mean'] = df['value'].rolling(window=3).mean()
df['expanding_sum'] = df['value'].expanding().sum()
print(df)
   value  rolling_mean  expanding_sum
0      1           NaN              1
1      2           NaN              3
2      3           2.0              6
3      4           3.0             10
4      5           4.0             15

Полезно для анализа временных рядов и трендов.

Цепочки преобразований через pipe

pipe позволяет последовательно применять несколько функций к DataFrame, улучшая читаемость.

Пример
def add_column(df, name, val):
    df[name] = val
    return df

def filter_positive(df, column):
    return df[df[column] > 0]

df = (pd.DataFrame({'a': [-1, 2, -3, 4]})
      .pipe(add_column, 'b', 10)
      .pipe(filter_positive, 'a'))
print(df)
   a   b
1  2  10
3  4  10

Это альтернатива вложенным вызовам или изменению данных в несколько шагов с копиями.

Библиотека Pandas для Python - comments

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