Сводная таблица в pandas с последовательностью rowid - PullRequest
0 голосов
/ 09 февраля 2020

У меня есть такие данные:

ID        Cue       trial     time     accuracy
A         apple     copy      1450     1 
A         dog       copy      2154     1
A         apple     test1     2121     0
A         dog       test2     0        1
A         apple     final     1231     0
A         dog       final     5411     1
B         apple     copy      818      0
B         ...       ...       ..      ...

И мне нужно преобразовать их так, чтобы каждая комбинация ID и Cue была в одной строке:

  A       apple   apple    apple   copy  test1   final   1450  2121  1231  1   0   0
  ...

В R, I это можно легко сделать с помощью data.table, используя dcast, например:

 dcast(data, ID + Cue ~ rowid(ID, Cue), value.var=c("time", "accuracy"))

Но в Pandas у меня проблема. Если я использую pivot_table, он не выходит правильно. Например, если я сделаю это:

 data.pivot_table(index=['ID', 'Cue', 'TrialType'], values=['time', 'accuracy'])

Это всегда будет выглядеть так:

 A      apple     copy     1450    1
                  final    1231    0
                  test1    2121    0

Проблема в том, что мне нужно, чтобы столбец «пробная версия» не складывался, но pivot_table / crosstab, похоже, не в состоянии справиться с этим. Имейте в виду, что если я добавлю «columns = 'trial" "в pivot_table, он не будет работать для моих целей, поскольку столбец" trial "используется в качестве категориальной переменной в моем анализе.

Любые подсказки приветствуются .

1 Ответ

1 голос
/ 09 февраля 2020

Копировать столбец Cue в новое Cue1 для второй позиции на DataFrame.insert, отменить поворот на DataFrame.melt, добавить счетчик на GroupBy.cumcount и измените на DataFrame.set_index с Series.unstack:

df.insert(1, 'Cue1', df['Cue'])
df = df.melt(['ID','Cue'])
df['g'] = df.groupby(['ID','Cue']).cumcount()
df = df.set_index(['ID', 'Cue', 'g'])['value'].unstack().reset_index(level=1, drop=True)
print (df)

g      0      1      2     3      4      5     6     7     8    9    10   11
ID                                                                          
A   apple  apple  apple  copy  test1  final  1450  2121  1231    1    0    0
A     dog    dog    dog  copy  test2  final  2154     0  5411    1    1    1
B   apple   copy    818     0    NaN    NaN   NaN   NaN   NaN  NaN  NaN  NaN

Другая идея:

c = df.columns.difference(['ID'], sort=False)
df = (df.groupby(['ID','Cue'])[c]
        .apply(lambda x: pd.DataFrame([x.T.values.ravel()]))
        .reset_index(level=[1,2], drop=True))
print (df)
        0      1      2     3      4      5       6       7       8    9   10  \
ID                                                                              
A   apple  apple  apple  copy  test1  final  1450.0  2121.0  1231.0  1.0  0.0   
A     dog    dog    dog  copy  test2  final  2154.0     0.0  5411.0  1.0  1.0   
B   apple   copy    818     0    NaN    NaN     NaN     NaN     NaN  NaN  NaN   

     11  
ID       
A   0.0  
A   1.0  
B   NaN  
...