Как сортировать мультииндексы (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/