pandas groupby и aggregate сохраняют ссылку с индексом

#python #pandas #dataframe #pandas-groupby #aggregate

#python #pandas #фрейм данных #pandas-groupby #агрегировать

Вопрос:

У меня есть DataFrame созданный случайным образом.

 d = {}
d['Model'] = ['M1', 'M2'] * 2 * 3 * 2
d['Support'] = ['S1', 'S1', 'S2', 'S2'] * 2 * 3
d['Group'] = ['G1', 'G2', 'G3'] * 2 * 2 * 2
val1 = []
val2 = []
random.seed(0)
for i in range (2*4*3):
    val1.append(random.randrange(-10, 11))
    val2.append(random.randrange(-10, 11))
d['val1'] = val1
d['val2'] = val2
 

Я группирую значения по Model , Support и Group :

 df_sum = df.groupby(['Model', 'Support', 'Group'])[['val1', 'val2']].sum()
df_sum


                        val1    val2
Model   Support  Group      
M1      S1       G1     -6      3
                 G2     14      11
                 G3     -16     16
        S2       G1     11      -2
                 G2     11      4
                 G3     -1      6
M2      S1       G1     -12     -1
                 G2     -4      5
                 G3     4       3
        S2       G1     5       -1
                 G2     5       -8
                 G3     -11     2
 

И я упорядочиваю столбцы по максимуму и минимуму.

 df_sum.groupby(level=['Support', 'Group']).agg([max, min])

                val1            val2
                max     min     max     min
Support Group               
S1      G1      -6      -12     3       -1
        G2      14      -4      11      5
        G3      4       -16     16      3
S2      G1      11      5       -1      -2
        G2      11      5       4       -8
        G3      -1     -11      6       2
 

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

Моя попытка:

 df_sum.groupby(level=['Support', 'Group']).agg([
    max,
    ('Model', lambda x: x.idxmax()[0]),
    min,
    ('Model', lambda x: x.idxmin()[0])
])


                val1                    val2
                max Model   min Model   max Model   min Model
Support Group                               
S1      G1      -6  M2      -12 M2      3   M2      -1  M2
        G2      14  M2      -4  M2      11  M2      5   M2
        G3      4   M1      -16 M1      16  M2      3   M2
S2      G1      11  M2      5   M2      -1  M1      -2  M1
        G2      11  M2      5   M2      4   M2      -8  M2
        G3      -1  M2      -11 M2      6   M2      2   M2
 

Очевидно, что значения в Model столбце неверны. Смотрим на первую таблицу:

 S1, G1, val1 = -6 -> M1 (not M2)
 

И так далее.

Ответ №1:

Я думаю, проблема должна быть в версии pandas, вы можете попробовать обновить.

Также решение было изменено pandas min и max функциями:

 df1 = df_sum.groupby(level=['Support', 'Group']).agg([
    ('max','max'),
    ('Model', lambda x: x.idxmax()[0]),
    ('min','min'),
    ('Model', lambda x: x.idxmin()[0])
   ])

print (df1)
              val1                 val2                
               max Model min Model  max Model min Model
Support Group                                          
S1      G1      -6    M1 -12    M2    3    M1  -1    M2
        G2      14    M1  -4    M2   11    M1   5    M2
        G3       4    M2 -16    M1   16    M1   3    M2
S2      G1      11    M1   5    M2   -1    M2  -2    M1
        G2      11    M1   5    M2    4    M1  -8    M2
        G3      -1    M1 -11    M2    6    M1   2    M2
 

Комментарии:

1. Хорошо, я обновился до pandas 1.1.3 (предыдущей версии 1.0.3 ), и ошибка исправлена. Вопрос @jezrael: почему вы используете (‘max’, ‘max’) и (‘min’, ‘min’) в aggregate() методе?

2. @PedroBiel — поскольку логика первая max — это новое имя столбца, а вторая max — агрегатная функция, здесь то же самое 😉 попробуйте ('maxcol', 'max') 😉

3. Понятно. Это может быть также (‘max’, max) .

4. @PedroBiel — да, тогда используется функция python max . Кстати, если использовать только max вместо ('max', max) этого в моей версии pandas, получаются странные имена столбцов с лямбдами.