Функция Pandas df.unstack()
df.unstack()является методом-членом DataFrame, используемым дляпреобразования индексов строк в индексы столбцов. Он "распаковывает" данные с иерархической индексацией, перемещая один или несколько уровней индекса строк в столбцы.
Это важная операция для изменения формы данных, обычно используется вместе сstack()для взаимного преобразования данных.
Определение слова: unstackОно означает "распаковать, развернуть"; здесь имеется в виду "разворачивание" индекса строк в столбцы, преобразование длинной таблицы в широкую.
Базовый синтаксис и параметры
df.unstack()Это метод экземпляра DataFrame, вызываемый через оператор точки.
Формат синтаксиса
DataFrame.unstack(level=-1, fill_value=None)
Описание параметра
- Параметр:
level- Тип: int, str, список int или список str.
- Описание: Задаёт уровень, который нужно развернуть в столбцы. Для многоуровневого индекса можно указать конкретный номер уровня (начиная с 0) или имя уровня. По умолчанию -1, что означает самый внутренний уровень.
- Параметр:
fill_value- Тип: скаляр или None.
- Описание: Значение, используемое для заполнения пропущенных значений, возникающих при операции unstack. По умолчанию None, при этом сохраняется NaN.
Описание функций
- Возвращаемое значение: Возвращает Series или DataFrame. Если разворачивается только один уровень строк исходного DataFrame, возвращается Series; в противном случае возвращается DataFrame.
- Действие: Перемещает один или несколько уровней индекса строк в индекс столбцов, создавая более широкий формат данных. Данные после unstack представлены в "широком формате", что упрощает просмотр и сравнение.
Примеры
На серии примеров от простого к сложному давайте тщательно освоимdf.unstack()его использование.
Пример 1: Базовое использование - Преобразование строк в столбцы
Пример
# 1. Создайте данные в длинном формате
df = pd.DataFrame({
'product': ['A', 'A', 'B', 'B', 'C', 'C'],
'region': ['North', 'South', 'North', 'South', 'North', 'South'],
'sales': [100, 150, 200, 180, 220, 250]
})
print("=== Исходные данные в длинном формате ===")
print(df)
# 2. Настройте иерархическую индексацию
df_indexed = df.set_index(['product', 'region'])
print("n=== После настройки иерархической индексации ===")
print(df_indexed)
# 3. Используйте df.unstack() для преобразования внутреннего индекса в столбцы
unstacked = df_indexed.unstack()
print("n=== результат df.unstack() ===")
print(unstacked)
# 4. Упрощённый вид
print("n=== Только продажи ===")
print(unstacked['sales'])
Ожидаемый вывод:
=== 原始长格式数据 ===
product region sales
0 A North 100
1 A South 150
2 B North 200
3 B South 180
4 C North 220
5 C South 250
n=== 设置层次化索引后 ===
sales
product region
A North 100
South 150
B North 200
South 180
C North 220
South 250
n=== df.unstack() 结果 ===
sales
region North South
product
A 100 150
B 200 180
C 220 250
n=== 只看销售额 ===
region North South
product
A 100 150
B 200 180
C 220 250
Пояснение к коду:
- Исходные данные находятся в длинном формате, где каждая строка содержит объем продаж продукта в регионе.
- Используйте
set_index()чтобы создать иерархический индекс (продукт как внешний уровень, регион как внутренний уровень). unstack()Внутренний индекс region перемещается в позицию столбца.- Результат представлен в широком формате, что позволяет интуитивно сравнивать данные о продажах для разных продуктов и регионов.
Пример 2: Разворачивание многоуровневого индекса
Когда DataFrame имеет многоуровневый индекс строк, можно указать, какой уровень развернуть.
Пример
# 1. Создать данные с многоуровневым индексом строк
df = pd.DataFrame({
'year': [2023, 2023, 2023, 2023, 2024, 2024, 2024, 2024],
'quarter': ['Q1', 'Q1', 'Q2', 'Q2', 'Q1', 'Q1', 'Q2', 'Q2'],
'product': ['A', 'B', 'A', 'B', 'A', 'B', 'A', 'B'],
'sales': [100, 150, 200, 180, 220, 250, 230, 270]
})
print("=== Исходные данные ===")
print(df)
# 2. Настроить многоуровневый индекс
df_indexed = df.set_index(['year', 'quarter', 'product'])
print("n=== После настройки многоуровневого индекса ===")
print(df_indexed)
# 3. Развернуть самый внутренний уровень (product, level=-1 по умолчанию)
print("n=== Развёрнутый уровень product (по умолчанию) ===")
unstacked_inner = df_indexed.unstack()
print(unstacked_inner['sales'])
# 4. Развернуть средний уровень (quarter)
print("n=== Развёрнутый уровень quarter ===")
unstacked_quarter = df_indexed.unstack(level='quarter')
print(unstacked_quarter['sales'])
# 5. Развернуть внешний уровень (year)
print("n=== Развёрнутый уровень year ===")
unstacked_year = df_indexed.unstack(level='year')
print(unstacked_year['sales'])
# 6. Развернуть несколько уровней одновременно
print("n=== Год и продукт вместе развёрнуты ===")
unstacked_multi = df_indexed.unstack(level=['year', 'product'])
print(unstacked_multi['sales'])
Ожидаемый вывод:
=== 原始数据 ===
year quarter product sales
0 2023 Q1 A 100
1 2023 Q1 B 150
2 2023 Q2 A 200
3 2023 Q2 B 180
4 2024 Q1 A 220
5 2024 Q1 B 250
6 2024 Q2 A 230
7 2024 Q2 B 270
n=== 设置多层索引 ===
sales
year quarter product
2023 Q1 A 100
B 150
Q2 A 200
B 180
2024 Q1 A 220
B 250
Q2 A 230
B 270
n=== 展开 product 层(默认)===
product A B
year quarter
2023 Q1 100 150
Q2 200 180
2024 Q1 220 250
Q2 230 270
n=== 展开 quarter 层 ===
quarter Q1 Q2
year product
2023 A 100 200
B 150 180
2024 A 220 230
B 250 270
n=== 展开 year 层 ===
year 2023 2024
quarter product
Q1 A 100 220
B 150 250
Q2 A 200 230
B 180 270
n=== 同时展开 year 和 product ===
year 2023 2024
product A B A B
quarter
Q1 100 150 220 250
Q2 200 180 230 270
Пояснение к коду:
- Для DataFrame с многоуровневым индексом можно использовать
levelпараметр, указывающий, какой уровень развернуть. - По умолчанию,
level=-1самый внутренний уровень (product) разворачивается. - Разворачивание разных уровней создаёт разные структуры данных, что позволяет удобно анализировать данные с разных точек зрения.
Пример 3: Обработка пропущенных значений с помощью fill_value
Используйтеfill_valueпараметр для заполнения пропущенных значений, возникающих после разворачивания.
Пример
import numpy as np
# 1. Создание неполных данных (не все комбинации product-region имеют данные)
df = pd.DataFrame({
'product': ['A', 'A', 'B', 'C'],
'region': ['North', 'South', 'North', 'Восток'],
'sales': [100, 150, 200, 220]
})
print("=== Исходные данные (неполные) ===")
print(df)
# 2. Создайте иерархический индекс и выполните unstack
df_indexed = df.set_index(['product', 'region'])
print("n=== Иерархический индекс ===")
print(df_indexed)
# 3. Не заполняйте пропущенные значения
print("n=== Без заполнения пропущенных значений ===")
unstacked = df_indexed.unstack()
print(unstacked)
print(f"Количество пропущенных значений: {unstacked['sales'].isna().sum().sum()}")
# 4. Используйте fill_value=0 для заполнения пропущенных значений
print("n=== fill_value=0 ===")
unstacked_fill = df_indexed.unstack(fill_value=0)
print(unstacked_fill)
print(f"Количество пропущенных значений: {unstacked_fill['sales'].isna().sum().sum()}")
Ожидаемый вывод:
=== 原始数据(不完整)===
product region sales
0 A North 100
1 A South 150
2 B North 200
3 C East 220
n=== 层次化索引 ===
sales
product region
A North 100
South 150
B North 200
C East 220
n=== 不填充缺失值 ===
sales
region East North South
product
A NaN 100.0 150.0
B NaN 200.0 NaN
C 220.0 NaN NaN
缺失值数量: 5
n=== fill_value=0 ===
sales
region East North South
product
A 0 100 150
B 0 200 0
C 220 0 0
缺失值数量: 0
Пояснение к коду:
- Когда исходные данные неполны, unstack создаёт пропущенные значения (NaN).
- Используя
fill_valueпараметр, можно указать значение заполнения, чтобы избежать ошибок в последующих вычислениях. - Обычно это заполняется 0, чтобы обозначить "нет данных" или "такая комбинация не существует".
Пример 4: Комбинирование unstack и stack
unstack()иstack()Это обратные операции; их совместное использование позволяет гибко изменять форму данных.
Пример
# 1. Создайте исходные данные в широком формате
df = pd.DataFrame({
'product': ['A', 'B', 'C'],
'Север': [100, 150, 200],
'South': [180, 170, 160],
'Восток': [190, 200, 210]
})
print("=== Исходные данные в широком формате ===")
print(df)
# 2. Сначала используйте stack для преобразования в длинный формат
print("n=== шаг 1: stack преобразует в длинный формат ===")
stacked = df.set_index('product').stack()
print(stacked)
# 3. Затем выполните unstack обратно (проверьте обратимость)
print("n=== шаг 2: unstack преобразует обратно в широкий формат ===")
restored = stacked.unstack()
print(restored)
# 4. Практика: переупорядочивание данных
print("n=== Практика: переместить регион в столбцы ===")
# Исходно: product как индекс строк, region как столбцы
# Цель: region как индекс строк, product как столбцы
result = df.set_index('product').unstack().unstack(level=-1)
print(result)
# 5. Используйте reorder_levels для настройки порядка уровней
print("n=== Использование reorder_levels для настройки уровней ===")
# Создание двухуровневого индекса
df_multi = pd.DataFrame(
[[100, 200], [150, 180], [190, 210]],
index=pd.MultiIndex.from_tuples([
('A', 'North'), ('B', 'North'), ('C', 'North')
], names=['product', 'region']),
columns=['2023', '2024']
)
print("Исходные данные:")
print(df_multi)
# Изменить порядок уровней
print("nПосле корректировки (год на внешнем уровне):")
print(df_multi.unstack(level='region'))
Ожидаемый вывод:
=== 原始宽格式数据 === product North South East 0 A 100 180 190 1 B 150 170 ...
Пояснение к коду:
stack()иunstack()Они — пара обратных операций.- Применение stack, а затем unstack теоретически может восстановить исходную форму (не учитывая различия в значениях заполнения).
- Различные компоновки данных можно получить с помощью разных комбинаций уровней.
- В реальном анализе данных часто требуется многократно изменять форму данных, чтобы соответствовать различным потребностям анализа.
Другие расширенияСовет:
unstack()иstack()Это ключевой инструмент для изменения формы данных.unstack()Он "распаковывает" строки в столбцы (из длинного в широкий),stack()Он "упаковывает" столбцы в строки (из широкого в длинный).
Pandas: общие функции