Точная обратная операция "pivot" панд - PullRequest
0 голосов
/ 10 сентября 2018

У меня есть датафрейм pandas в грубом формате

print(df)
    Time  GroupA  GroupB  Value1  Value2
0  100.0     1.0     1.0    18.0     0.0
1  100.0     1.0     2.0    16.0     0.0
2  100.0     2.0     1.0    18.0     0.0
3  100.0     2.0     2.0    10.0     0.0

, где Time - переменная счета / отметка времени, GroupA и GroupB - категории, а Value1 и Value2 - числовые величины. Этот фрагмент кода создает макет dataframe:

import numpy as np
values = np.zeros(shape=(4,5))
values[:,0] = 100
values[:,1] = [1]*2 + [2]*2
values[:,2] = [1,2]*2
values[:,3] = np.random.randint(low=10,high=20,size=(4))
df = pd.DataFrame(values,columns=['Time','GroupA','GroupB','Value1','Value2'])

После загрузки некоторых данных я хочу вычислить и заполнить значения Value2. Поскольку это происходит (поскольку, кстати, Value2 является функцией временного ряда Value1 в каждой существующей (GroupA, GroupB) паре), я обнаружил, что проще всего рассчитать эти значения, сначала переместив мои данные в форма:

df_pivot = df.pivot_table(index='Time',columns=['GroupA','GroupB'],values=['Value1','Value2'], fill_value=0.0)

Затем после некоторого несвязанного кода я заполнил значения

print(df_pivot)
       Value1             Value2            
GroupA    1.0     2.0        1.0     2.0    
GroupB    1.0 2.0 1.0 2.0    1.0 2.0 1.0 2.0
Time                                        
100.0      13  16  16  10     27  20  28  20

Теперь я хочу «откатить» это обратно в исходный формат df. Я мог бы сделать это вручную, перебрав df, найдя значение в df_pivot и заполнив его, но я бы предпочел использовать встроенные функции. Попробуйте, как я мог бы использовать варианты df.melt, я не могу выполнить эту инверсию из-за проблем с иерархическими столбцами df_pivot. Моя лучшая попытка

dfm = df_pivot.reset_index().melt(id_vars="Time")
dfm.columns.values[1] = "HACK"
dfm = dfm.pivot_table(index=["Time","GroupA","GroupB"],columns="HACK",values="value").reset_index()

, который создает фрейм данных

print(dfm)
HACK   Time  GroupA  GroupB  Value1  Value2
0     100.0     1.0     1.0      13      27
1     100.0     1.0     2.0      16      20
2     100.0     2.0     1.0      16      28
3     100.0     2.0     2.0      10      20

Это работает, но не кажется мне лучшим решением или очень переносимым (почему melt создает имя столбца "NaN"? Почему я вручную нахожу индекс этого столбца и переименовываю его? Почему Я должен поворачиваться, чтобы отменить поворот?) Экспериментируя и просматривая документацию и примеры альтернативы, я в растерянности, хотя. Функция melt имеет аргумент col_level, который выглядит так, как будто он должен помочь, но любое допустимое значение, которое я использую для этого, просто приводит к потере данных (потеря данных "Time", "GroupA" или "GroupB").

1 Ответ

0 голосов
/ 10 сентября 2018

Я думаю stack проще

df_pivot.stack([1,2]).reset_index()
Out[8]: 
    Time  GroupA  GroupB  Value1  Value2
0  100.0     1.0     1.0      13       0
1  100.0     1.0     2.0      13       0
2  100.0     2.0     1.0      12       0
3  100.0     2.0     2.0      11       0
...