pandas группирует и расширяет фрейм данных упорядоченными столбцами

#python-3.x #pandas #pivot

#python-3.x #панды #сводная

Вопрос:

У меня есть фрейм данных длинной формы, который содержит несколько выборок и временных точек для каждого субъекта. Количество выборок и временной момент могут варьироваться, а дни между временными точками также могут различаться:

 test_df = pd.DataFrame({"subject_id":[1,1,1,2,2,3],
                    "sample":["A", "B", "C", "D", "E", "F"],
                    "timepoint":[19,11,8,6,2,12],
                    "time_order":[3,2,1,2,1,1]
 })

   subject_id   sample  timepoint   time_order
0    1            A        19           3
1    1            B        11           2
2    1            C         8           1
3    2            D         6           2
4    2            E         2           1
5    3            F        12           1
  

Мне нужно найти способ обобщить группировку этого фрейма данных по subject_id и поместить все выборки и временные точки в одну строку в порядке времени.

ЖЕЛАЕМЫЙ РЕЗУЛЬТАТ:

     subject_id  sample1 timepoint1  sample2   timepoint2  sample3 timepoint3
0    1            C         8         B        11        A      19                              
1    2            E         2         D         6       null   null         
5    3            F        12        null      null     null   null   
  

Pivot приближает меня, но я застрял на том, как действовать дальше:

 test_df = test_df.pivot(index=['subject_id', 'sample'],
columns='time_order', values='timepoint')
  

введите описание изображения здесь

Ответ №1:

Используйте DataFrame.set_index with DataFrame.unstack для поворота, сортировки мультииндекса по столбцам, сглаживания и последнего преобразования subject_id в столбец:

 df = (test_df.set_index(['subject_id', 'time_order'])
             .unstack()
             .sort_index(level=[1,0], axis=1))
df.columns = df.columns.map(lambda x: f'{x[0]}{x[1]}')
df = df.reset_index()
print (df)
   subject_id sample1  timepoint1 sample2  timepoint2 sample3  timepoint3
0           1       C         8.0       B        11.0       A        19.0
1           2       E         2.0       D         6.0     NaN         NaN
2           3       F        12.0     NaN         NaN     NaN         NaN
  

Ответ №2:

 a=test_df.iloc[:,:3].groupby('subject_id').last().add_suffix('1')
b=test_df.iloc[:,:3].groupby('subject_id').nth(-2).add_suffix('2')
c=test_df.iloc[:,:3].groupby('subject_id').nth(-3).add_suffix('3')
pd.concat([a, b,c], axis=1)

    

            sample1  timepoint1 sample2  timepoint2 sample3  timepoint3
subject_id                                                            
1                C           8       B        11.0       A        19.0
2                E           2       D         6.0     NaN         NaN
3                F          12     NaN         NaN     NaN         NaN