Как сортировать мультииндексы (MultiIndex) в Pandas

Синтаксис сортировки MultiIndex:

.sort_values(by=[('Level 1', 'Level 2')], ascending=False)

Для сортировки MultiIndex необходимо указать все уровни, которые будут использоваться для сортировки. Иначе появиться ошибку типа:

ValueError: The column label 'Depth' is not unique.
For a multi-index, the label must be a tuple with elements corresponding to each level.

Шаг 1: Создание многоиндексного DataFrame

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

Исходный DataFrame:

Magnitude Type Depth Magnitude
MB 100.0 5.6
MWC 10.0 5.5
MWW 21.0 6.0
MWC 35.0 5.5
MWB 45.0 5.6

Для этого DataFrame мы хотим сгруппировать данные по 'Magnitude Type' и получить среднее значение, количество и сумму для столбцов — 'Depth', 'Magnitude'.

df_multi = df.groupby(['Magnitude Type'])[['Depth', 'Magnitude']].agg(['mean', 'count', 'sum'])

В результате:

Depth Magnitude
mean count sum mean count sum
Magnitude Type
MB 81.579365 3761 306819.990 5.682957 3761 21373.60
MD 21.670000 6 130.020 5.966667 6 35.80
MH 8.074600 5 40.373 6.540000 5 32.70
ML 14.158273 77 1090.187 5.814675 77 447.73
MS 30.142226 1702 51302.068 5.994360 1702 10202.40
MW 77.034037 7722 594856.835 5.933794 7722 45820.76
MWB 76.989829 2458 189241.000 5.907282 2458 14520.10
MWC 66.808213 5669 378735.760 5.858176 5669 33210.00
MWR 22.445385 26 583.580 5.630769 26 146.40
MWW 67.568545 1983 133988.425 6.008674 1983 11915.20

В следующем шаге мы рассмотрим, как сортировать MultiIndex.

Шаг 2: Найти уровни MultiIndex

Давайте посмотрим, что хранится в качестве MultiIndex в приведенном выше DataFrame. Поскольку у нас есть MultiIndex для столбцов, мы можем получить информацию об уровнях:

df_multi.columns

Результат:

MultiIndex([(    'Depth',  'mean'),
            (    'Depth', 'count'),
            (    'Depth',   'sum'),
            ('Magnitude',  'mean'),
            ('Magnitude', 'count'),
            ('Magnitude',   'sum')],
           )

Чтобы получить конкретный уровень, мы можем сделать:

df_multi.columns.get_level_values(1)

Результат:

Index(['mean', 'count', 'sum', 'mean', 'count', 'sum'], dtype='object')

Шаг 3: Сортировка мультииндексов в Pandas

Теперь предположим, что мы хотим отсортировать по среднему значению, которое находится под Depth. Из предыдущего шага мы видели, что нам нужно использовать: [('Depth', 'mean')] для параметра by:

df_multi.sort_values(by=[('Depth', 'mean')], ascending=False).head(60)

Теперь значения сортируются по паре Depth — mean.

Depth Magnitude
mean count sum mean count sum
Magnitude Type
MB 81.579365 3761 306819.990 5.682957 3761 21373.60
MW 77.034037 7722 594856.835 5.933794 7722 45820.76
MWB 76.989829 2458 189241.000 5.907282 2458 14520.10
MWW 67.568545 1983 133988.425 6.008674 1983 11915.20
MWC 66.808213 5669 378735.760 5.858176 5669 33210.00

Шаг 4: Сортировка мультииндекса по нескольким уровням

Что если вы хотите отсортировать MultiIndex по нескольким уровням? В этом случае вы можете использовать следующий синтаксис:

df_multi.sort_values(by=[('Depth', 'mean'), ('Depth', 'sum')], ascending=False)

Сортировка произведется:

  • сначала по — ('Depth', 'mean')
  • далее по — ('Depth', 'sum')

Шаг 5: Сортировка MultiIndex по номеру уровня

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

В этом случае вы можете прочитать информацию об уровне из Шага 2 и использовать ее.

Например, сортировка MultiIndex по третьему уровню будет выглядеть так: df_multi.columns[2] — что эквивалентно ('Depth', 'sum'):

df_multi.sort_values(by=[df_multi.columns[2]], ascending=False).head(5)

Источник: https://datascientyst.com/sort-multiindex-pandas/