DataFrame в Pandas — создание и основные операции
Что такое DataFrame
DataFrame — двумерная таблица в pandas. Строки и столбцы, как в Excel или SQL-таблице, но в Python. Каждый столбец — это Series с одним типом данных. DataFrame — основная структура, с которой аналитик работает в pandas: загрузил данные, отфильтровал, сгруппировал, посчитал метрику.
import pandas as pdВесь дальнейший код предполагает, что pandas импортирован как pd.
Создание DataFrame
Из словаря (dict)
Самый частый способ. Ключи становятся именами столбцов, значения — данными.
df = pd.DataFrame({
'user_id': [1, 2, 3],
'city': ['Москва', 'Питер', 'Казань'],
'revenue': [1500, 3200, 800]
})Из списка словарей (list of dicts)
Каждый словарь — одна строка. Удобно, когда данные приходят из API в виде JSON.
data = [
{'user_id': 1, 'city': 'Москва', 'revenue': 1500},
{'user_id': 2, 'city': 'Питер', 'revenue': 3200},
{'user_id': 3, 'city': 'Казань', 'revenue': 800},
]
df = pd.DataFrame(data)Из списка списков (list of lists)
Имена столбцов передаются отдельно через columns:
df = pd.DataFrame(
[[1, 'Москва', 1500],
[2, 'Питер', 3200],
[3, 'Казань', 800]],
columns=['user_id', 'city', 'revenue']
)Из CSV-файла
В реальной работе данные чаще всего загружаются из файла. Подробно о параметрах — в статье про read_csv.
df = pd.read_csv('orders.csv')
df = pd.read_csv('data.tsv', sep='\t')
df = pd.read_csv('sales.csv', parse_dates=['order_date'])Осмотр DataFrame
После создания или загрузки — первым делом осмотр. Набор команд, который нужно довести до автоматизма:
df.shape # (кол-во строк, кол-во столбцов)
df.head() # первые 5 строк
df.tail(3) # последние 3 строки
df.info() # типы данных + количество пропусков
df.describe() # статистика по числовым столбцам
df.dtypes # типы данных по столбцам
df.columns # список имён столбцовinfo() показывает количество non-null значений — по нему сразу видно, где есть пропуски. describe() выдаёт count, mean, std, min, max и квартили — быстрый способ заметить аномалии в данных.
Выбор столбцов
# Один столбец — возвращает Series
df['city']
# Несколько столбцов — возвращает DataFrame
df[['user_id', 'city']]Через точку тоже работает (df.city), но это ломается, если имя столбца совпадает с методом DataFrame или содержит пробелы. Используйте квадратные скобки — они надёжнее.
Фильтрация строк
Булева маска в квадратных скобках — основной способ:
# Выручка больше 1000
df[df['revenue'] > 1000]
# Несколько условий — каждое в скобках
df[(df['revenue'] > 1000) & (df['city'] == 'Москва')]
# Фильтр по списку значений
df[df['city'].isin(['Москва', 'Питер'])]Для одновременного выбора строк и столбцов используйте loc и iloc:
df.loc[df['revenue'] > 1000, ['user_id', 'revenue']]Добавление и удаление столбцов
Добавление
# Новый столбец через присваивание
df['revenue_k'] = df['revenue'] / 1000
# Столбец на основе условия
df['is_big'] = df['revenue'] > 2000
# assign — создаёт копию с новыми столбцами
df = df.assign(
revenue_k=df['revenue'] / 1000,
tax=df['revenue'] * 0.2
)Удаление
df = df.drop(columns=['revenue_k'])
# Несколько столбцов
df = df.drop(columns=['tax', 'is_big'])Переименование столбцов
df = df.rename(columns={'revenue': 'total_revenue', 'city': 'region'})
# Переименовать все столбцы разом
df.columns = ['id', 'region', 'total']Сортировка
# По одному столбцу
df.sort_values('revenue', ascending=False)
# По нескольким
df.sort_values(['city', 'revenue'], ascending=[True, False])
# Сортировка по индексу
df.sort_index()Базовая статистика
df['revenue'].mean() # среднее
df['revenue'].median() # медиана
df['revenue'].sum() # сумма
df['revenue'].std() # стандартное отклонение
df['revenue'].min() # минимум
df['revenue'].max() # максимум
df['city'].nunique() # количество уникальных значений
df['city'].value_counts() # частота каждого значенияvalue_counts() — один из самых полезных методов для первичного анализа. Показывает распределение категориальной переменной за один вызов.
reset_index
После фильтрации или группировки индекс может стать непоследовательным. reset_index() сбрасывает его:
filtered = df[df['revenue'] > 1000]
filtered = filtered.reset_index(drop=True)drop=True убирает старый индекс. Без этого параметра старый индекс станет отдельным столбцом.
После groupby результат часто имеет мультииндекс — reset_index() превращает его обратно в обычный DataFrame:
stats = df.groupby('city')['revenue'].sum().reset_index()Практические примеры
Подготовка данных для анализа
df = pd.read_csv('events.csv')
df['created_at'] = pd.to_datetime(df['created_at'])
df = df.rename(columns={'amt': 'amount'})
df = df[df['amount'] > 0]
df = df.sort_values('created_at').reset_index(drop=True)
df.shapeЗагрузка, приведение типов, переименование, фильтрация мусора, сортировка. Пять строк — и данные готовы к анализу.
Быстрый профиль столбца
col = df['revenue']
print(f'Строк: {len(col)}, Пропусков: {col.isna().sum()}')
print(f'Мин: {col.min()}, Макс: {col.max()}, Медиана: {col.median()}')
print(f'Уникальных: {col.nunique()}')Частые ошибки
SettingWithCopyWarning
Самая распространённая ловушка для начинающих:
# Плохо — pandas не гарантирует, что это изменит оригинал
filtered = df[df['city'] == 'Москва']
filtered['revenue'] = 0 # SettingWithCopyWarning
# Хорошо — явная копия
filtered = df[df['city'] == 'Москва'].copy()
filtered['revenue'] = 0
# Хорошо — изменение через loc
df.loc[df['city'] == 'Москва', 'revenue'] = 0Правило: если отфильтровали DataFrame и хотите менять значения — используйте .copy() или loc.
Chained indexing
# Плохо — непредсказуемый результат
df[df['city'] == 'Москва']['revenue'] = 0
# Хорошо — одна операция через loc
df.loc[df['city'] == 'Москва', 'revenue'] = 0Цепочка df[...][...] создаёт промежуточный объект, и присваивание может применяться к копии, а не к оригиналу. Всегда используйте loc для присвоения по условию.
Вопросы с собеседований
— Как создать DataFrame из словаря?
— pd.DataFrame({'col1': [1, 2], 'col2': [3, 4]}). Ключи словаря — имена столбцов, значения — списки данных. Все списки должны быть одинаковой длины.
— Чем DataFrame отличается от Series? — Series — одномерный массив с индексом (один столбец). DataFrame — двумерная таблица, состоящая из нескольких Series. Один столбец DataFrame — это Series.
— Как узнать количество строк и столбцов?
— df.shape возвращает кортеж (строки, столбцы). Количество строк отдельно — len(df).
— Как избежать SettingWithCopyWarning?
— Использовать .copy() при создании подмножества, если планируете его изменять. Для изменения значений в оригинале — df.loc[условие, столбец] = значение.
— Зачем нужен reset_index?
— После фильтрации или groupby индекс может быть непоследовательным или многоуровневым. reset_index(drop=True) создаёт чистый числовой индекс с нуля.
FAQ
Чем DataFrame отличается от SQL-таблицы?
Концептуально — ничем: строки, столбцы, типы данных. На практике DataFrame живёт в оперативной памяти Python-процесса и поддерживает операции, которых нет в SQL: произвольные функции через apply, встроенная визуализация, интеграция с NumPy и scikit-learn. SQL-таблица живёт на сервере базы данных и лучше масштабируется.
Когда использовать list of dicts, а когда dict of lists?
Dict of lists — когда вы строите таблицу по столбцам (знаете все значения каждого столбца заранее). List of dicts — когда данные приходят построчно: из API, из цикла, из JSON. Результат идентичен, выбирайте по удобству.
Можно ли создать пустой DataFrame и добавлять строки?
Можно: df = pd.DataFrame(columns=['a', 'b']), затем pd.concat([df, new_row]). Но добавление строк в цикле — антипаттерн: каждый concat копирует весь DataFrame. Лучше собрать данные в список и создать DataFrame один раз.
Что учить после основ DataFrame?
Фильтрацию через loc и iloc, группировку через groupby, загрузку данных через read_csv. Вся шпаргалка по pandas — в одном месте.
Что дальше
Основы DataFrame — фундамент для всей работы с pandas. Дальше — группировка (groupby), индексация (loc и iloc), загрузка данных (read_csv). Больше вопросов по Python — в каталоге, тренажёр по Python — на отдельной странице.
Чтобы закрепить тему на практике — откройте тренажёр и порешайте вопросы по Pandas прямо в Telegram.