melt, pivot_table и explode: широкий и длинный форматы
Содержание курса
Сводная таблица с агрегацией через pd.pivot_table
pd.melt идёт в одну сторону — из широкого формата в длинный. pd.pivot_table — в обратную: берёт длинную таблицу и строит из неё агрегированный широкий формат.
Представим такую таблицу продаж:
import pandas as pd
df_sales = pd.DataFrame({
'city': ['Москва', 'Москва', 'Казань', 'Казань', 'Москва'],
'month': ['Jan', 'Feb', 'Jan', 'Feb', 'Jan'],
'revenue': [100, 200, 150, 130, 80]
})
Здесь несколько строк с одинаковой парой city + month (Москва, Jan встречается дважды). Мы хотим получить таблицу, где строки — города, столбцы — месяцы, а в ячейках — суммарная выручка:
pt = pd.pivot_table(
df_sales,
index='city', # уникальные значения этого столбца станут строками
columns='month', # уникальные значения этого столбца станут столбцами
values='revenue', # что агрегировать
aggfunc='sum' # как агрегировать
)
print(pt)
Вывод:
month Feb Jan city Казань 130 150 Москва 200 180
Параметры по смыслу:
index— столбец, чьи уникальные значения образуют строки результата.columns— столбец, чьи уникальные значения образуют столбцы результата.values— столбец с числами, которые нужно агрегировать.aggfunc— функция агрегации:'sum','mean','count'или любая Python-функция. По умолчанию'mean'— это частая причина неожиданных результатов, поэтому всегда указывай явно.
Именованный индекс и как от него избавиться
У результата pivot_table есть особенность: city становится именованным индексом, а month — именем оси столбцов. Это не ошибка, но если нужна плоская таблица без индекса — вызывай reset_index():
pt_flat = pt.reset_index()
print(pt_flat)
Вывод:
month city Feb Jan 0 Казань 130 150 1 Москва 200 180
После reset_index() city превращается в обычный столбец, индекс становится стандартным RangeIndex. Обрати внимание: метка month над строкой столбцов никуда не девается — это columns.name, оставшееся от параметра columns='month'. Это косметика API, не влияющая на данные; при необходимости убирается через pt_flat.columns.name = None.
Ещё одна частая ситуация — пропуски в результате. Если для какой-то комбинации строка/столбец данных нет, pivot_table ставит NaN. Параметр fill_value позволяет заменить их нулём или любым другим значением:
pt = pd.pivot_table(
df_sales,
index='city',
columns='month',
values='revenue',
aggfunc='sum',
fill_value=0
)
Сводная таблица, построенная через pivot_table, — это полноценный DataFrame, с которым можно работать дальше: сортировать, фильтровать, применять rank или cumsum по строкам или столбцам.
