На самом деле, я думаю, вы нашли пару ошибок!
Ошибка №1 - Изменение dtype с помощью set_levels с помощью pd.Categorical не работает.
import pandas as pd
import numpy as np
d = {
'Card': [
'Visa', 'Visa', 'Master Card', 'Master Card', 'Visa', 'Master Card',
'Visa', 'Visa', 'Master Card', 'Visa', 'Master Card', 'Visa', 'Visa',
'Master Card', 'Master Card', 'Visa', 'Master Card', 'Visa', 'Visa',
'Master Card', 'Visa', 'Master Card', 'Master Card', 'Master Card',
'Master Card', 'Master Card', 'Master Card', 'Visa', 'Visa'
],
'Year': [
'Three', 'Three', 'Seven', 'Three', 'Three', 'Seven', 'Seven', 'Seven',
'Three', 'Seven', 'Three', 'Three', 'Three', 'Seven', 'Three', 'Three',
'Seven', 'Seven', 'Seven', 'Three', 'Seven', 'Three', 'Five', 'One',
'One', 'Two', 'Four', 'Six', 'Six'
],
'Value': [
45, 13, 52, 321, 31, 1231, 876, 231, 4, 213, 123, 45, 321, 1, 123, 52,
736, 35, 900, 301, 374, 9, 294, 337, 4465, 321, 755, 22, 8
]
}
df = pd.DataFrame(d)
grp_cols = ['Card', 'Year']
ser_val = df.groupby(grp_cols)['Value'].mean()
#---------------------------------------------
#Attempt 1st
categories_order = ['One', 'Two', 'Three', 'Four', 'Five', 'Six', 'Seven']
categories = pd.Categorical(ser_val.index.levels[1].values,
categories=categories_order,
ordered=True)
ser_val.index.set_levels(categories, level=1, inplace=True)
print(ser_val.index.levels[1].dtype)
#--------------------------------------------
#Attempt 2nd
categories_order = ['One', 'Two', 'Three', 'Four', 'Five', 'Six', 'Seven']
categories = pd.Categorical(ser_val.index.levels[1].values,
categories=categories_order,
ordered=True)
ser_val.index = ser_val.index.set_levels(categories, level='Year')
print(ser_val.index.levels[1].dtype)
#----------------------------------
#Attempt 3rd and success
categories_order = ['One', 'Two', 'Three', 'Four', 'Five', 'Six', 'Seven']
categoriesDtype = pd.CategoricalDtype(categories_order, ordered=True)
ser_val.index = ser_val.index.set_levels(ser_val.index.levels[1].astype(categoriesDtype), level='Year')
print(ser_val.index.levels[1].dtype)
Вывод:
object *FAILED change type using inplace*
object *FAILED change type using reassignment*
category *SUCCESS change type using pd.CategoricalDtype*
Ошибка №2 - sort_index с использованием категориального для MultiIndex уровня 1 не работает
После успешного изменения типа для уровня индекса 1:
ser_val.index.levels[1]
Вывод:
CategoricalIndex(['Five', 'Four', 'One', 'Seven', 'Six', 'Three', 'Two'], categories=['One', 'Two', 'Three', 'Four', 'Five', 'Six', 'Seven'], ordered=True, name='Year', dtype='category')
Теперь давайте отсортируем фрейм данных с помощью sort_index:
ser_val.sort_index()
Вывод (НЕИСПРАВНОСТЬ):
Card Year
Master Card Five 294.000000
Four 755.000000
One 2401.000000
Seven 505.000000
Three 146.833333
Two 321.000000
Visa Seven 438.166667
Six 15.000000
Three 84.500000
Name: Value, dtype: float64
Теперь, просто для удовольствия и тестирования, давайте поменяем уровни индекса и попробуем снова sort_index.
ser_val.swaplevel(0,1).sort_index()
Вывод (УСПЕХ):
Year Card
One Master Card 2401.000000
Two Master Card 321.000000
Three Master Card 146.833333
Visa 84.500000
Four Master Card 755.000000
Five Master Card 294.000000
Six Visa 15.000000
Seven Master Card 505.000000
Visa 438.166667
Name: Value, dtype: float64
Однако, если мы явно установили уровни сортировки ... снова FAIL.
ser_val.swaplevel(0,1).sort_index(level=[0,1])
Вывод:
Year Card
Five Master Card 294.000000
Four Master Card 755.000000
One Master Card 2401.000000
Seven Master Card 505.000000
Visa 438.166667
Six Visa 15.000000
Three Master Card 146.833333
Visa 84.500000
Two Master Card 321.000000
Name: Value, dtype: float64