Pandas: библиотека анализа данных в 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
Это альтернатива вложенным вызовам или изменению данных в несколько шагов с копиями.