March 31, 2022

Отмена вращения матрицы (unpivot) средствами Pandas

Операция обратная pivot (получению сводной формы) в Pandas реализована функцией melt. Для демонстрации ее применения сгенерируем датафрейм:

import pandas as pd

df = pd.DataFrame([['Ромашка', 2020, 'orange', 21], ['Ромашка', 2021, 'banana', 22], ['Ромашка', 2020,'слива', 12],
                  ['Роза', 2020, 'orange', 15], ['Роза', 2021,'banana', 31], ['Роза', 2021,'слива', 83]
                  ], columns=['firm', 'year', 'product', 'count'])

df = df.pivot(index=['firm', 'year'], columns='product', values='count')
df.columns.name=''

df = df.reset_index()
df

Melt преобразует матрицу в форму:

индексные_столбцы...имя_столбца...значение_столбца

Вызовем эту функцию на наших данных и посмотрим, что получится (индексные столбцы - 'firm' и 'year', остальные - колонки значений)

id_cols = ['firm', 'year']

melt_df = pd.melt(df, id_vars=id_cols, var_name='product', 
                  value_vars=df.columns.difference(id_cols))
melt_df

Как можно заметить, через переменную var_name можно задать имя столбца с наименованиями колонок.

Полученные данные можно вернуть в широкий формат функцией pivot:

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

melt_df = pd.melt(df.reset_index(), id_vars='index', value_vars=df.columns, var_name = 'columns')
melt_df
pd.pivot(melt_df, index='index', columns='columns', values='value')

Если в функцию melt в качестве параметр id_vars передать колонки, которые не характеризуют однозначно другие столбцы, то вернуть широкий формат станет проблемой:

id_cols = ['firm']
melt_df = pd.melt(df, id_vars=id_cols, var_name='product', 
                  value_vars=df.columns.difference(id_cols))
melt_df
pd.pivot(melt_df, index='firm', columns='product', values='value')

Действительно, теперь возникают неоднозначности, например, для пары Роза, banana есть два value, и не понятно, какое из низ выбрать.