Функция Pandas df.unstack()

Pandas 常用函数Pandas: общие функции


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: Базовое использование - Преобразование строк в столбцы

Пример

import pandas as pd

# 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

Пояснение к коду:

  1. Исходные данные находятся в длинном формате, где каждая строка содержит объем продаж продукта в регионе.
  2. Используйтеset_index()чтобы создать иерархический индекс (продукт как внешний уровень, регион как внутренний уровень).
  3. unstack()Внутренний индекс region перемещается в позицию столбца.
  4. Результат представлен в широком формате, что позволяет интуитивно сравнивать данные о продажах для разных продуктов и регионов.

Пример 2: Разворачивание многоуровневого индекса

Когда DataFrame имеет многоуровневый индекс строк, можно указать, какой уровень развернуть.

Пример

import pandas as pd

# 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 pandas as pd
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()Это обратные операции; их совместное использование позволяет гибко изменять форму данных.

Пример

import pandas as pd

# 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 常用函数Pandas: общие функции

Другие расширения