TLDR; перейти к последней части (нет необходимости создавать новый столбец для логического маскирования в первую очередь!)
Теперь, чтобы ответить на ваш вопрос ...
В вашем DataFrame нет ничего плохого! С вашим подходом вы пропускаете только один шаг. Получение значений из .levels[]
- это только первый шаг.
import pandas as pd
import numpy as np
iterables = [['bar', 'baz', 'foo', 'qux'], ['one', 'two']]
mult_index = pd.MultiIndex.from_product(iterables, names=['first', 'second'])
df = pd.DataFrame(np.random.randn(8, 3), index=mult_index, columns=['A', 'B', 'C'])
mult_index # same as df.index
Будет выведено:
MultiIndex(levels=[['bar', 'baz', 'foo', 'qux'], ['one', 'two']],
labels=[[0, 0, 1, 1, 2, 2, 3, 3], [0, 1, 0, 1, 0, 1, 0, 1]],
names=['first', 'second'])
Отсюда вы видите, что возврата значений levels
недостаточно. Вы также должны отобразить эти значения на соответствующие значения labels
. Длина labels
будет равна количеству строк.
df['index_val1'] = [ mult_index.levels[0][i] for i in mult_index.labels[0]]
или
df['index_val1'] = [ df.index.levels[0][i] for i in df.index.labels[0]]
Для этого отображения есть встроенная функция!
df['index_val1'] = df.index.get_level_values(0)
На самом деле вы можете просто использовать get_level_values
, чтобы выполнить все ваши логические маскировки. Нет необходимости создавать дополнительный столбец .
df[ df.index.get_level_values(0)=='bar']