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