Освойте изменение формы данных с помощью сводных таблиц Python Pandas. Подробное изучение синтаксиса, продвинутых методов и практических примеров для глобального анализа данных.
Сводные таблицы Python Pandas: исчерпывающее руководство по изменению формы данных
В мире анализа данных возможность суммировать, агрегировать и реструктурировать данные — это не просто навык, это суперспособность. Необработанные данные в своем естественном виде часто напоминают обширную подробную книгу. Она богата информацией, но трудна для интерпретации. Чтобы извлечь содержательные выводы, нам нужно преобразовать эту книгу в краткое изложение. Именно здесь сводные таблицы преуспевают, а для программистов Python библиотека Pandas предоставляет мощный и гибкий инструмент: pivot_table().
Это руководство предназначено для глобальной аудитории аналитиков данных, ученых и энтузиастов Python. Мы углубимся в механику сводных таблиц Pandas, переходя от фундаментальных концепций к продвинутым методам. Независимо от того, суммируете ли вы данные о продажах из разных континентов, анализируете данные о климате в разных регионах или отслеживаете показатели проекта для распределенной команды, освоение сводных таблиц коренным образом изменит ваш подход к исследованию данных.
Что такое сводная таблица?
Если вы когда-либо использовали программное обеспечение для работы с электронными таблицами, такое как Microsoft Excel или Google Sheets, вам, вероятно, знакомо понятие сводной таблицы. Это интерактивная таблица, которая позволяет реорганизовывать и суммировать выбранные столбцы и строки данных из большего набора данных для получения желаемого отчета.
Сводная таблица выполняет две ключевые задачи:
- Агрегация: вычисляет сводную статистику (например, сумму, среднее значение или количество) для числовых данных, сгруппированных по одной или нескольким категориям.
- Изменение формы: преобразует данные из «длинного» формата в «широкий» формат. Вместо того, чтобы иметь все значения в одном столбце, он «сводит» уникальные значения из столбца в новые столбцы в выходных данных.
Функция Pandas pivot_table() переносит эту мощную функциональность непосредственно в ваш рабочий процесс анализа данных Python, обеспечивая воспроизводимое, сценарийное и масштабируемое изменение формы данных.
Настройка среды и образцов данных
Прежде чем мы начнем, убедитесь, что у вас установлена библиотека Pandas. Если нет, вы можете установить ее с помощью pip, установщика пакетов Python:
pip install pandas
Теперь давайте импортируем ее в наш скрипт Python или блокнот:
import pandas as pd
import numpy as np
Создание глобального набора данных о продажах
Чтобы сделать наши примеры практическими и актуальными для всего мира, мы создадим синтетический набор данных, представляющий данные о продажах для многонациональной компании электронной коммерции. Этот набор данных будет включать информацию о продажах из разных регионов, стран и категорий продуктов.
# Create a dictionary of data
data = {
'TransactionID': range(1, 21),
'Date': pd.to_datetime([
'2023-01-15', '2023-01-16', '2023-01-17', '2023-02-10', '2023-02-11',
'2023-02-12', '2023-03-05', '2023-03-06', '2023-03-07', '2023-01-20',
'2023-01-21', '2023-02-15', '2023-02-16', '2023-03-10', '2023-03-11',
'2023-01-18', '2023-02-20', '2023-03-22', '2023-01-25', '2023-02-28'
]),
'Region': [
'North America', 'Europe', 'Asia', 'North America', 'Europe', 'Asia', 'North America', 'Europe', 'Asia', 'Europe',
'Asia', 'North America', 'Europe', 'Asia', 'North America', 'Asia', 'Europe', 'North America', 'Europe', 'Asia'
],
'Country': [
'USA', 'Germany', 'Japan', 'Canada', 'France', 'India', 'USA', 'UK', 'China', 'Germany',
'Japan', 'USA', 'France', 'India', 'Canada', 'China', 'UK', 'USA', 'Germany', 'India'
],
'Product_Category': [
'Electronics', 'Apparel', 'Electronics', 'Books', 'Apparel', 'Electronics', 'Books', 'Electronics', 'Apparel',
'Apparel', 'Books', 'Electronics', 'Books', 'Apparel', 'Electronics', 'Books', 'Apparel', 'Books', 'Electronics', 'Electronics'
],
'Units_Sold': [10, 5, 8, 20, 7, 12, 15, 9, 25, 6, 30, 11, 18, 22, 14, 28, 4, 16, 13, 10],
'Unit_Price': [1200, 50, 900, 15, 60, 1100, 18, 950, 45, 55, 12, 1300, 20, 40, 1250, 14, 65, 16, 1150, 1050]
}
# Create DataFrame
df = pd.DataFrame(data)
# Calculate Revenue
df['Revenue'] = df['Units_Sold'] * df['Unit_Price']
# Display the first few rows of the DataFrame
print(df.head())
Этот набор данных дает нам прочную основу со смесью категориальных данных (Region, Country, Product_Category), числовых данных (Units_Sold, Revenue) и данных временных рядов (Date).
Анатомия pivot_table()
Функция Pandas pivot_table() невероятно универсальна. Давайте разберем ее наиболее важные параметры:
pandas.pivot_table(data, values=None, index=None, columns=None, aggfunc='mean', fill_value=None, margins=False, margins_name='All')
- data: DataFrame, который вы хотите развернуть.
- values: Столбец(ы), содержащий(ие) данные для агрегирования. Если не указано, будут использоваться все остальные числовые столбцы.
- index: Столбец(ы), чьи уникальные значения будут формировать строки новой сводной таблицы. Это иногда называют «ключом группировки».
- columns: Столбец(ы), чьи уникальные значения будут «сведены» для формирования столбцов новой таблицы.
- aggfunc: Функция агрегирования, применяемая к «значениям». Это может быть строка, например «sum», «mean», «count», «min», «max», или функция, например
np.sum. Вы также можете передать список функций или словарь для применения различных функций к различным столбцам. По умолчанию используется «mean». - fill_value: Значение для замены любых отсутствующих результатов (NaN) в сводной таблице.
- margins: Логическое значение. Если установлено значение
True, добавляет промежуточные итоги для строк и столбцов (также известные как общий итог). - margins_name: Имя для строки/столбца, содержащего итоги, когда
margins=True. По умолчанию используется «All».
Ваша первая сводная таблица: простой пример
Начнем с распространенного бизнес-вопроса: «Каков общий доход, полученный по каждой категории продуктов?»
Чтобы ответить на это, нам нужно:
- Использовать
Product_Categoryдля строк (index). - Агрегировать столбец
Revenue(values). - Использовать сумму в качестве нашей функции агрегирования (aggfunc).
# Simple pivot table to see total revenue by product category
category_revenue = pd.pivot_table(df,
values='Revenue',
index='Product_Category',
aggfunc='sum')
print(category_revenue)
Вывод:
Revenue
Product_Category
Apparel 1645
Books 1184
Electronics 56850
Мгновенно у нас есть четкое, краткое изложение. Журнал транзакций в необработанном виде, состоящий из 20 строк, был преобразован в таблицу из 3 строк, которая непосредственно отвечает на наш вопрос. Это фундаментальная сила сводной таблицы.
Добавление измерения столбца
Теперь давайте расширим это. Что, если мы хотим видеть общий доход по каждой категории продуктов, но также с разбивкой по регионам? Именно здесь вступает в действие параметр columns.
# Pivot table with index and columns
revenue_by_category_region = pd.pivot_table(df,
values='Revenue',
index='Product_Category',
columns='Region',
aggfunc='sum')
print(revenue_by_category_region)
Вывод:
Region Asia Europe North America Product_Category Apparel 1125.0 625.0 NaN Books 336.0 360.0 488.0 Electronics 13200.0 14550.0 29100.0
Этот результат гораздо богаче. Мы свели уникальные значения из столбца «Region» («Asia», «Europe», «North America») в новые столбцы. Теперь мы можем легко сравнить, как разные категории продуктов работают в разных регионах. Мы также видим значение NaN (Not a Number). Это указывает на то, что в нашем наборе данных не было зарегистрировано продаж «Apparel» для «North America». Это само по себе ценная информация!
Продвинутые методы сведения
Основы мощны, но истинная гибкость pivot_table() раскрывается в ее расширенных функциях.
Обработка отсутствующих значений с помощью fill_value
NaN в нашей предыдущей таблице является точным, но для отчетности или дальнейших вычислений может быть предпочтительнее отображать его как ноль. Параметр fill_value упрощает это.
# Using fill_value to replace NaN with 0
revenue_by_category_region_filled = pd.pivot_table(df,
values='Revenue',
index='Product_Category',
columns='Region',
aggfunc='sum',
fill_value=0)
print(revenue_by_category_region_filled)
Вывод:
Region Asia Europe North America Product_Category Apparel 1125 625 0 Books 336 360 488 Electronics 13200 14550 29100
Таблица теперь чище и ее легче читать, особенно для нетехнической аудитории.
Работа с несколькими индексами (иерархическое индексирование)
Что, если вам нужно сгруппировать данные по нескольким категориям в строках? Например, давайте разделим продажи по Region, а затем по Country в каждом регионе. Мы можем передать список столбцов параметру index.
# Multi-level pivot table using a list for the index
multi_index_pivot = pd.pivot_table(df,
values='Revenue',
index=['Region', 'Country'],
aggfunc='sum',
fill_value=0)
print(multi_index_pivot)
Вывод:
Revenue
Region Country
Asia China 488
India 1760
Japan 10860
Europe France 1020
Germany 14440
UK 1115
North America Canada 17800
USA 12058
Pandas автоматически создал MultiIndex в строках. Эта иерархическая структура фантастически подходит для детализации ваших данных и просмотра вложенных связей. Вы можете применить ту же логику к параметру columns для создания иерархических столбцов.
Использование нескольких функций агрегирования
Иногда одной сводной статистики недостаточно. Возможно, вы захотите увидеть как общий доход (сумма), так и средний размер транзакции (среднее значение) для каждой группы. Вы можете передать список функций в aggfunc.
# Using multiple aggregation functions
multi_agg_pivot = pd.pivot_table(df,
values='Revenue',
index='Region',
aggfunc=['sum', 'mean', 'count'])
print(multi_agg_pivot)
Вывод:
sum mean count
Revenue Revenue Revenue
Region
Asia 13108.000000 2184.666667 6
Europe 16575.000000 2762.500000 6
North America 29858.000000 4976.333333 6
Эта единственная команда дает нам исчерпывающий итог: общий доход, средний доход на транзакцию и количество транзакций для каждого региона. Обратите внимание, как Pandas создает иерархические столбцы, чтобы поддерживать порядок в выходных данных.
Применение различных функций к различным значениям
Вы можете получить еще более детальную информацию. Представьте, что вы хотите увидеть сумму Revenue, но среднее значение Units_Sold. Вы можете передать словарь в aggfunc, где ключами являются имена столбцов («values»), а значениями — желаемые функции агрегирования.
# Different aggregations for different values
dict_agg_pivot = pd.pivot_table(df,
index='Region',
values=['Revenue', 'Units_Sold'],
aggfunc={
'Revenue': 'sum',
'Units_Sold': 'mean'
},
fill_value=0)
print(dict_agg_pivot)
Вывод:
Revenue Units_Sold
Region
Asia 13108 17.833333
Europe 16575 8.166667
North America 29858 14.333333
Этот уровень контроля делает pivot_table() первоклассным инструментом для сложного анализа данных.
Вычисление общих итогов с помощью margins
Для целей отчетности наличие итогов по строкам и столбцам часто имеет важное значение. Аргумент margins=True обеспечивает это без дополнительных усилий.
# Adding totals with margins=True
revenue_with_margins = pd.pivot_table(df,
values='Revenue',
index='Product_Category',
columns='Region',
aggfunc='sum',
fill_value=0,
margins=True,
margins_name='Grand Total') # Custom name for totals
print(revenue_with_margins)
Вывод:
Region Asia Europe North America Grand Total Product_Category Apparel 1125 625 0 1750 Books 336 360 488 1184 Electronics 13200 14550 29100 56850 Grand Total 14661 15535 29588 59784
Pandas автоматически вычисляет сумму для каждой строки (общий доход по каждой категории продуктов во всех регионах) и каждого столбца (общий доход по каждому региону по всем категориям), а также общий итог для всех данных в правом нижнем углу.
Практический пример использования: анализ на основе времени
Сводные таблицы не ограничиваются статическими категориями. Они невероятно полезны для анализа данных временных рядов. Давайте найдем общий доход за каждый месяц.
Сначала нам нужно извлечь месяц из нашего столбца «Date». Мы можем использовать аксессор .dt в Pandas для этого.
# Extract month from the Date column
df['Month'] = df['Date'].dt.month_name()
# Pivot to see monthly revenue by product category
monthly_revenue = pd.pivot_table(df,
values='Revenue',
index='Month',
columns='Product_Category',
aggfunc='sum',
fill_value=0)
# Optional: Order the months correctly
month_order = ['January', 'February', 'March']
monthly_revenue = monthly_revenue.reindex(month_order)
print(monthly_revenue)
Вывод:
Product_Category Apparel Books Electronics Month January 250 360 23100 February 795 794 24250 March 705 30 9500
Эта таблица дает нам четкое представление об эффективности продаж каждой категории с течением времени, позволяя нам легко выявлять тенденции, сезонность или аномалии.
pivot_table() vs. groupby(): В чем разница?
Это распространенный вопрос для тех, кто изучает Pandas. Эти две функции тесно связаны, и на самом деле pivot_table() построена на основе groupby().
groupby()— это более общая и фундаментальная операция. Она группирует данные на основе определенных критериев, а затем позволяет применить функцию агрегирования. Результатом обычно является Pandas Series или DataFrame с иерархическим индексом, но он остается в «длинном» формате.pivot_table()— это специализированный инструмент, который выполняет group-by, а затем изменяет форму данных. Его основная цель — преобразовать данные из длинного формата в широкий формат, который часто более удобочитаем.
Давайте вернемся к нашему первому примеру с использованием groupby():
# Same result as our first pivot table, but using groupby
category_revenue_groupby = df.groupby('Product_Category')['Revenue'].sum()
print(category_revenue_groupby)
Результатом является Pandas Series, который функционально эквивалентен DataFrame из нашей первой сводной таблицы. Однако, когда вы вводите второй ключ группировки (например, «Region»), разница становится очевидной.
# Grouping by two columns
groupby_multi = df.groupby(['Product_Category', 'Region'])['Revenue'].sum()
print(groupby_multi)
Вывод (Series с MultiIndex):
Product_Category Region
Apparel Asia 1125
Europe 625
Books Asia 336
Europe 360
North America 488
Electronics Asia 13200
Europe 14550
North America 29100
Name: Revenue, dtype: int64
Чтобы получить тот же «широкий» формат, что и pivot_table(index='Product_Category', columns='Region'), вам нужно использовать groupby(), за которым следует unstack():
# Replicating a pivot table with groupby().unstack()
groupby_unstack = df.groupby(['Product_Category', 'Region'])['Revenue'].sum().unstack(fill_value=0)
print(groupby_unstack)
Это дает точно такой же результат, что и наша сводная таблица со столбцами. Таким образом, вы можете думать о pivot_table() как об удобном ярлыке для общего рабочего процесса groupby().aggregate().unstack().
Когда что использовать?
- Используйте
pivot_table(), когда вам нужны удобочитаемые выходные данные в широком формате, особенно для отчетности или создания перекрестных таблиц. - Используйте
groupby(), когда вам нужна большая гибкость, вы выполняете промежуточные вычисления в конвейере обработки данных или когда измененный широкий формат не является вашей конечной целью.
Производительность и лучшие практики
Хотя pivot_table() является мощным инструментом, важно использовать его эффективно, особенно с большими наборами данных.
- Сначала фильтруйте, потом сводите: Если вам нужно проанализировать только подмножество ваших данных (например, продажи за последний год), отфильтруйте DataFrame перед применением сводной таблицы. Это уменьшает объем данных, которые функция должна обработать.
- Используйте категориальные типы: Для столбцов, которые вы часто используете в качестве индексов или столбцов в своих сводных таблицах (например, «Region» или «Product_Category»), преобразуйте их в тип данных «category» в Pandas. Это может значительно снизить использование памяти и ускорить операции группировки.
df['Region'] = df['Region'].astype('category') - Сохраняйте удобочитаемость: Избегайте создания сводных таблиц со слишком большим количеством индексов и столбцов. Хотя это возможно, сводная таблица шириной в сотни столбцов и длиной в тысячи строк может стать такой же нечитаемой, как и исходные необработанные данные. Используйте ее для создания целевых итогов.
- Разберитесь с агрегированием: Помните о своем выборе
aggfunc. Использование «sum» для цен не имеет смысла, а «mean» может быть более подходящим. Всегда убедитесь, что ваше агрегирование соответствует вопросу, на который вы пытаетесь ответить.
Заключение: Ваш инструмент для содержательных итогов
Функция Pandas pivot_table() является незаменимым инструментом в наборе инструментов любого аналитика данных. Она предоставляет декларативный, выразительный и мощный способ перейти от запутанных, подробных данных к чистым, содержательным итогам. Понимая и осваивая ее основные компоненты — values, index, columns и aggfunc — и используя ее расширенные функции, такие как многоуровневое индексирование, пользовательские агрегирования и поля, вы можете изменить форму своих данных, чтобы ответить на сложные бизнес-вопросы всего несколькими строками кода Python.
В следующий раз, когда вы столкнетесь с большим набором данных, сопротивляйтесь желанию прокручивать бесконечные строки. Вместо этого подумайте о вопросах, на которые вам нужно ответить, и о том, как сводная таблица может изменить форму ваших данных, чтобы раскрыть скрытые в них истории. Счастливого сведения!