Python
Pandas Unstack: A Beginner's Guide to Reshaping Data

Pandas Unstack: Руководство для начинающих по преобразованию данных

MoeNagy Dev

Понимание pandas unstack

Объяснение pandas unstack

Что такое pandas unstack?

unstack() - это функция pandas, которая преобразует DataFrame из длинного формата в широкий формат. Она берет многоуровневый столбцовый индекс и "разворачивает" его, создавая новый DataFrame, в котором один или несколько уровней индекса становятся столбцами.

Чем она отличается от pivot и melt?

Функция unstack() похожа на функцию pivot(), но они служат разным целям. pivot() используется для преобразования данных из длинного формата в широкий формат, в то время как unstack() используется для преобразования данных из широкого формата в длинный формат.

Функция melt(), с другой стороны, используется для преобразования данных из широкого формата в длинный формат, что является противоположным тому, что делает unstack().

Когда использовать pandas unstack?

Вы должны использовать unstack(), когда у вас есть DataFrame с многоуровневым столбцовым индексом, и вы хотите преобразовать его в широкий формат, где уровни столбцового индекса становятся новыми столбцами в DataFrame.

Подготовка данных

Импорт необходимых библиотек

import pandas as pd
import numpy as np

Создание примера DataFrame

# Создание примера DataFrame
data = {
    ('Store A', 'Sales'): [100, 120, 80, 90, 110],
    ('Store A', 'Profit'): [20, 25, 15, 18, 22],
    ('Store B', 'Sales'): [150, 180, 120, 160, 200],
    ('Store B', 'Profit'): [30, 35, 25, 32, 40]
}
 
df = pd.DataFrame(data)

Исследование структуры DataFrame

print(df)
           (Store A, Sales)  (Store A, Profit)  (Store B, Sales)  (Store B, Profit)
0  .Вот перевод на русский язык:

Продажи Прибыль Магазин А Магазин Б Магазин А Магазин Б 0 100 150 20 30 1 120 180 25 35 2 80 120 15 25 3 90 160 18 32 4 110 200 22 40


Как вы можете видеть, DataFrame имеет многоуровневый столбцовый индекс, где первый уровень представляет магазин, а второй уровень представляет метрику (Продажи или Прибыль).

### Основы разворачивания pandas

#### Разворачивание одноуровневого индекса

Чтобы развернуть одноуровневый индекс, вы можете использовать функцию `unstack()` без каких-либо аргументов:

```python
df_unstacked = df.unstack()
print(df_unstacked)
                 Продажи        Прибыль
                 Магазин А Магазин Б Магазин А Магазин Б
0                    100     150       20       30
1                    120     180       25       35
2                     80     120       15       25
3                     90     160       18       32
4                    110     200       22       40

Полученный DataFrame имеет названия магазинов в качестве столбцового индекса, а исходные названия столбцов (Продажи и Прибыль) стали индексом строк.

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

Если DataFrame имеет многоуровневый столбцовый индекс, вы можете указать уровень для разворачивания:

df_unstacked = df.unstack(level=0)
print(df_unstacked)
                  (Продажи, Магазин А)  (Продажи, Магазин Б)  (Прибыль, Магазин А)  (Прибыль, Магазин Б)
0                             100               150                 20                 30
1                             120               180                 25                 35
2                              80               120                 15                 25
3                              90               160                 18                 32
4                             110            .
```Вот перевод на русский язык:

В этом случае названия магазинов стали индексами столбцов, а исходные названия столбцов (Продажи и Прибыль) теперь являются частью многоуровневого индекса столбцов.

Понимание структуры полученного DataFrame

Разверстанный DataFrame имеет многоуровневый индекс столбцов, где первый уровень представляет исходные названия столбцов, а второй уровень представляет значения, которые ранее были в индексе столбцов.

Эта структура может быть полезна для определенных типов анализа данных и визуализации, так как она позволяет легко получать доступ к данным и манипулировать ими различными способами.

Обработка пропущенных данных в pandas unstack

Работа с NaN-значениями

Если в исходном DataFrame есть какие-либо пропущенные значения, функция unstack() введет NaN-значения в результирующем DataFrame:

# Добавим некоторые пропущенные значения в исходный DataFrame
data = {
    ('Магазин А', 'Продажи'): [100, 120, 80, np.nan, 110],
    ('Магазин А', 'Прибыль'): [20, 25, 15, 18, 22],
    ('Магазин Б', 'Продажи'): [150, 180, 120, 160, 200],
    ('Магазин Б', 'Прибыль'): [30, 35, 25, 32, np.nan]
}
 
df = pd.DataFrame(data)
df_unstacked = df.unstack()
print(df_unstacked)
                 Продажи        Прибыль
                 Магазин А Магазин Б Магазин А Магазин Б
0                    100     150       20     30.0
1                    120     180       25     35.0
2                     80     120       15     25.0
3                    NaN     160       18     32.0
4                    110     200       22      NaN

Вы можете видеть, что пропущенные значения в исходном DataFrame были перенесены в разверстанный DataFrame.

Заполнение пропущенных значений

Чтобы обработать пропущенные значения, вы можете использовать метод fillna() для замены их на определенное значение:

df_unstacked = df.unstack().fillna(0)
print(df_unstacked)
                 Продажи        Прибыль
                 Магазин А Магазин Б Магазин А Магазин Б
0                    100     150       20     30.0
1                    120     180       25     35.0
2                     80     120       15     25.0
3                      0     160       18     32.0
4                    110     200       22      0
```Вот перевод файла на русский язык с сохранением комментариев к коду:

30
1                    120     180       25       35
2                     80     120       15       25
3                      0     160       18       32
4                    110     200       22        0

В этом примере мы заполняем пропущенные значения нулями.

Указание значения для заполнения

Вы также можете указать другое значение для заполнения, например, среднее или медианное значение столбца:

# Заполнить пропущенные значения средним значением столбца
df_unstacked = df.unstack().fillna(df.mean())
print(df_unstacked)
                 Sales        Profit
                 Store A Store B Store A Store B
0                    100     150       20     32.5
1                    120     180       25     32.5
2                     80     120       15     32.5
3                    95.0     160       18     32.5
4                    110     200       22     22.0

В этом примере мы заполняем пропущенные значения средним значением соответствующих столбцов.

Продвинутые техники с pandas unstack

Разворачивание с указанием уровней

Вы также можете развернуть определенные уровни индекса столбцов, а не все уровни:

# Развернуть второй уровень индекса столбцов
df_unstacked = df.unstack(level=1)
print(df_unstacked)
                   Sales   Profit
Store A  0            100       20
         1            120       25
         2             80       15
         3            NaN       18
         4            110       22
Store B  0            150       30
         1            180       35
         2            120       25
         3            160       32
         4            200       NaN

В этом случае названия магазинов стали индексом строк, а исходные названия столбцов (Sales и Profit) стали индексом столбцов.

Комбинирование unstack с другими операциями pandas

Вы можете комбинировать функцию unstack() с другими операциями pandas, такими как reset_index() или rename(), для дальнейшей обработки данных:

# Развернуть и сбросить индекс
```Вот перевод на русский язык:
 
df_unstacked = df.unstack().reset_index()
print(df_unstacked)
  level_0 level_1   0         1
0  Store A  Sales  100       20
1  Store A  Sales  120       25
2  Store A  Sales   80       15
3  Store A  Sales  NaN       18
4  Store A  Sales  110       22
5  Store B  Sales  150       30
6  Store B  Sales  180       35
7  Store B  Sales  120       25
8  Store B  Sales  160       32
9  Store B  Sales  200       NaN

В этом примере мы разделили DataFrame и затем сбросили индекс, что создает новый DataFrame с разделенными значениями в одном столбце.

Сброс индекса после разделения

Если вы хотите сбросить индекс после разделения, вы можете использовать метод reset_index():

# Разделить и сбросить индекс
df_unstacked = df.unstack().reset_index()
print(df_unstacked)
  level_0 level_1   0         1
0  Store A  Sales  100       20
1  Store A  Sales  120       25
2  Store A  Sales   80       15
3  Store A  Sales  NaN       18
4  Store A  Sales  110       22
5  Store B  Sales  150       30
6  Store B  Sales  180       35
7  Store B  Sales  120       25
8  Store B  Sales  160       32
9  Store B  Sales  200       NaN

Это создает новый DataFrame с разделенными значениями в одном столбце, а исходные уровни индекса теперь являются столбцами в DataFrame.

Визуализация разделенных данных

Создание тепловых карт

Один из способов визуализировать разделенные данные - создать тепловую карту с использованием библиотеки seaborn:

import seaborn as sns
import matplotlib.pyplot as plt
 
# Разделить DataFrame
df_unstacked = df.unstack()
 
# Создать тепловую карту
plt.figure(figsize=(8, 6))
sns.heatmap(df_unstacked, annot=True, cmap="YlOrRd")
plt.title("Продажи и прибыль по магазинам")
plt.show()

Это создаст тепловую карту, которая визуализирует данные о продажах и прибыли для каждого магазина.

Создание сводных таблиц

Вы также можете использовать функцию pivot_table() для создания сводной таблицы из разделенных данных:

# Создать сводную таблицу
pivot_table = ...
```Вот перевод на русский язык:
 
e = df.pivot_table(index=['Магазин'], columns=['Метрика'], values=['Значение'])
print(pivot_table)
 

Значение Метрика Прибыль Продажи Магазин A 20 100 25 120 15 80 18 NaN 22 110 Магазин B 30 150 35 180 25 120 32 160 NaN 200


Этот сводный отчет имеет названия магазинов в качестве индекса строк и названия метрик в качестве индекса столбцов, а соответствующие значения - в ячейках.

#### Построение неразвернутых данных

Вы также можете непосредственно построить неразвернутые данные, например, создать столбчатую или линейную диаграмму:

```python
# Построить неразвернутые данные
df_unstacked.plot(kind="bar", figsize=(10, 6))
plt.title("Продажи и прибыль по магазинам")
plt.xlabel("Магазин")
plt.ylabel("Значение")
plt.show()

Это создаст столбчатую диаграмму, показывающую значения продаж и прибыли для каждого магазина.

Практические применения pandas unstack

Анализ данных о продажах

Разворачивание может быть полезно для анализа данных о продажах, особенно когда у вас есть многоуровневый индекс столбцов. Вы можете использовать развернутые данные для создания сводных таблиц, тепловых карт или других визуализаций, чтобы лучше понять тенденции и показатели продаж в разных магазинах, по разным продуктам или за разные периоды времени.

Преобразование временных рядов

unstack() также может быть полезен для преобразования данных временных рядов, когда у вас есть многоуровневый индекс с временем и еще одним измерением (например, местоположение, продукт). Развернув данные, вы можете создать широкоформатную таблицу данных, которая проще в работе для определенных типов анализа и визуализации.

Обработка данных опросов

В случае данных опросов, когда у вас есть ответы на разные вопросы для каждого участника, unstack() можно использовать для преобразования данных из длинного формата в широкий формат, что упрощает анализ взаимосвязей между различными вопросами опроса.

Устранение неполадок и лучшие практики

Распространенные проблемы и сообщения об ошибках

Одна из распространенных проблем с unstack() заключается в том, что она может вводить.Вот перевод на русский язык:

Функции

Функции - это многократно используемые блоки кода, которые выполняют определенную задачу. Они могут принимать входные параметры, выполнять операции и возвращать значение. Функции помогают организовывать и модуляризировать ваш код, делая его более читаемым и поддерживаемым.

Вот пример простой функции, которая вычисляет площадь круга:

def calculate_circle_area(radius):
    """
    Вычисляет площадь круга.
 
    Аргументы:
        radius (float): Радиус круга.
 
    Возвращает:
        float: Площадь круга.
    """
    pi = 3.14159
    area = pi * (radius ** 2)
    return area
 
# Пример использования
circle_radius = 5.0
circle_area = calculate_circle_area(circle_radius)
print(f"Площадь круга с радиусом {circle_radius} составляет {circle_area:.2f} квадратных единиц.")

В этом примере функция calculate_circle_area принимает параметр radius, вычисляет площадь по формуле pi * (radius ** 2) и возвращает результат. Функция также включает в себя строку документации, которая кратко описывает назначение функции, ее входной параметр и возвращаемое значение.

Модули и пакеты

Модульный дизайн Python позволяет организовывать ваш код в многократно используемые компоненты, называемые модулями. Модули - это файлы Python, которые содержат определения для переменных, функций и классов. Импортируя модули, вы можете получить доступ и использовать код, который они предоставляют.

Вот пример того, как создать и использовать пользовательский модуль:

# my_module.py
def greet(name):
    print(f"Привет, {name}!")
 
# main.py
import my_module
 
my_module.greet("Алиса")

В этом примере мы создаем модуль под названием my_module.py, который содержит функцию greet. В файле main.py мы импортируем my_module и вызываем функцию greet.

Пакеты - это коллекции связанных модулей. Они помогают организовывать ваш код и предоставляют способ группировать и распространять ваш Python-код. Вот пример простой структуры пакета:

my_package/
    __init__.py
    module1.py
```Вот перевод на русский язык:

    module2.py
    subpackage/
        __init__.py
        module3.py

В этом примере my_package - это пакет, который содержит два модуля (module1.py и module2.py) и подпакет (subpackage). Файлы __init__.py в пакете и подпакете используются для определения структуры и поведения пакета.

Объектно-ориентированное программирование (ООП)

Объектно-ориентированное программирование (ООП) - это парадигма программирования, которая фокусируется на создании объектов, содержащих как данные (атрибуты), так и функции (методы) для представления и манипулирования этими данными. ООП предоставляет концепции, такие как классы, наследование и полиморфизм, которые помогают создавать более организованный и многоразовый код.

Вот пример простого класса на Python:

class Dog:
    def __init__(self, name, breed):
        self.name = name
        self.breed = breed
 
    def bark(self):
        print("Гав!")
 
# Пример использования
my_dog = Dog("Buddy", "Лабрадор")
print(my_dog.name)  # Вывод: Buddy
print(my_dog.breed)  # Вывод: Лабрадор
my_dog.bark()  # Вывод: Гав!

В этом примере мы определяем класс Dog с методом __init__, который инициализирует атрибуты name и breed. Класс также имеет метод bark, который выводит "Гав!". Затем мы создаем экземпляр класса Dog и обращаемся к его атрибутам и методу.

ООП также предоставляет концепцию наследования, при которой дочерний класс может наследовать атрибуты и методы от родительского класса. Вот пример:

class GuideDog(Dog):
    def __init__(self, name, breed, can_guide):
        super().__init__(name, breed)
        self.can_guide = can_guide
 
    def guide(self):
        print("Я могу направлять своего хозяина.")
 
# Пример использования
my_guide_dog = GuideDog("Buddy", "Лабрадор", True)
print(my_guide_dog.name)  # Вывод: Buddy
print(my_guide_dog.breed)  # Вывод: Лабрадор
print(my_guide_dog.can_guide)  # Вывод: True
my_guide_dog.bark()  # Вывод: Гав!
my_guide_dog.guide()  # Вывод: Я могу направлять своего хозяина.

В этом примере класс GuideDog наследует от класса Dog.Вот перевод на русский язык:

Исключения и обработка ошибок

Исключения - это события, которые происходят во время выполнения программы и нарушают нормальный ход выполнения инструкций программы. Python имеет встроенный механизм обработки исключений, который позволяет вам предвидеть и обрабатывать эти исключения.

Вот пример того, как обрабатывать исключение ZeroDivisionError:

def divide(a, b):
    try:
        result = a / b
        return result
    except ZeroDivisionError:
        print("Ошибка: Деление на ноль.")
        return None
 
# Пример использования
print(divide(10, 2))  # Вывод: 5.0
print(divide(10, 0))  # Вывод: Ошибка: Деление на ноль.

В этом примере функция divide пытается разделить a на b в блоке try. Если возникает ZeroDivisionError, выполняется код в блоке except, и выводится сообщение. Затем функция возвращает None, чтобы указать, что операция деления была неуспешной.

Вы также можете использовать блок finally, чтобы выполнить код независимо от того, было ли вызвано исключение или нет. Это полезно для очистки ресурсов, таких как закрытие файла или соединения с базой данных.

try:
    file = open("file.txt", "r")
    content = file.read()
    print(content)
except FileNotFoundError:
    print("Ошибка: Файл не найден.")
finally:
    file.close()

В этом примере блок finally гарантирует, что файл будет закрыт, даже если в блоке try возникнет исключение.

Заключение

В этом учебном пособии по Python мы рассмотрели широкий спектр тем, включая функции, модули и пакеты, объектно-ориентированное программирование и обработку исключений. Эти концепции являются фундаментальными для написания эффективного и поддерживаемого кода на Python.

Понимание и применение этих техник позволит вам .Вы на пути к тому, чтобы стать опытным программистом на Python. Помните, что регулярная практика, эксперименты с различными примерами кода и изучение обширной экосистемы библиотек и фреймворков Python помогут расширить ваши знания и навыки.

Счастливого кодирования!

MoeNagy Dev.