Если вы работаете с данными в Python, то, скорее всего, ваша правая рука (а может, и левая) – это библиотека Pandas. Часто данные поступают нам в одном формате, а для эффективного анализа, визуализации или моделирования требуется совершенно другой. И важно уметь делать преобразования между "длинным" (long) и "широким" (wide) форматами датаферйма.
Мы не только подробно разберем, что представляют собой длинный и широкий форматы, но и освоим два ключевых инструмента Pandas для их взаимного преобразования: `pivot_table` и `melt`.
import pandas as pd
import seaborn as sns
# Загружаем датасет flights
flights_df = sns.load_dataset('flights')
# Узнаем размеры датафрейма
print(flights_df.shape)
# (144, 3)
# Посмотрим на первые 5 строк
display(flights_df.head())
# Получим информацию о датафрейме
flights_df.info()
# Превращаем месяцы в колонки, годы оставляем в индексе, значения - пассажиры
flights_wide_df = flights_df.pivot_table(index='year',
columns='month',
values='passengers',
aggfunc='sum')
# aggfunc='sum' здесь для явности,
# т.к. для flights дубликатов (год, месяц) нет
display(flights_wide_df)
Совет
А что если у нас несколько колонок для `index` или `values`? `pivot_table` справится и с этим! Например, если бы в нашем датасете был столбец `quarter` (квартал), мы могли бы указать `index=['year', 'quarter']` для создания иерархического индекса, где каждая строка идентифицировалась бы уникальной комбинацией года и квартала. Подобным образом, если бы мы хотели агрегировать и представить в таблице несколько различных числовых показателей (скажем, `passengers` и `avg_ticket_price`), мы могли бы передать их списком в параметр `values`: `values=['passengers', 'avg_ticket_price']`. В таком случае Pandas автоматически создаст соответствующую структуру с многоуровневыми столбцами, если это необходимо для отображения всех комбинаций.
# Сначала сбросим индекс у flights_wide_df, чтобы 'year' стал обычной колонкой
flights_wide_reset_df = flights_wide_df.reset_index()
# Теперь "плавим" данные обратно в длинный формат
flights_long_again_df = flights_wide_reset_df.melt(id_vars=['year'],
var_name='month',
value_name='passengers')
print(flights_df.shape)
# (144, 3)
display(flights_long_again_df)
Лайфхак
Не стоит рассматривать выбор формата как однократное и окончательное решение. В реальном рабочем процессе анализа данных часто приходится многократно преобразовывать данные. Например, вы можете начать с длинного формата для очистки и некоторых агрегаций, затем преобразовать данные в широкий формат для расчета новых признаков или для передачи в модель, а затем, возможно, снова вернуться к длинному формату (или его части) для создания специфических визуализаций. Pandas и его функции, такие как `pivot_table`, `melt`, `stack`, `unstack`, созданы именно для такой гибкой работы. Главное – четко понимать, какой формат нужен для каждого шага, и уметь его получить.