Гармонизировать панды MultiIndex в строку при чтении файлов Excel - PullRequest
0 голосов
/ 28 января 2019

Я читаю данные из файла Excel в pandas DataFrame, используя read_excel().К сожалению, кажется, что трудно обеспечить форматирование ячеек в Excel, и получается, что таблица, подобная этой:

       2018                2019
          a         b         a         b
0  1.295666 -0.544973  0.845973 -0.874668
1  0.590123  0.284364 -1.482706 -0.859350
2  0.832228  0.469992  0.994865  0.480301
3  0.098671  0.198643  0.878323 -0.119761

... на самом деле имеет удивительные индексы или столбцы:

df.columns

MultiIndex(levels=[[2018, 2019, '2019'], ['a', 'b']],
           labels=[[0, 0, 1, 2], [0, 1, 0, 1]])

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

Чтобы быть в безопасности, я хотел бы преобразовать все индексы в str ing, но панды не позволят мне:

df.columns.set_levels(df.columns.levels[0].astype(str), level=0)

ValueError: Level values must be unique: ['2018', '2019', '2019'] on level 0

Я вижу два подхода для решения этой проблемы:

  1. Пусть read_excel() преобразовать заголовки столбцов в строку или
  2. Получите set_levels(), как в моем примере выше, чтобы работать.

Но я не могузаставить либо работать - какие-нибудь намеки?

1 Ответ

0 голосов
/ 28 января 2019

Вы можете заново создать несколько index для столбцов

idx=pd.MultiIndex.from_product([df.columns.levels[0].astype(int).unique(),df.columns.levels[1]])
df.columns=idx
df.columns
MultiIndex(levels=[[2018, 2019], ['a', 'b']],
           labels=[[0, 0, 1, 1], [0, 1, 0, 1]])

Из лучшего формата макета

df.columns = pd.MultiIndex.from_product([c.astype(str).unique() for c in df.columns.levels])

Обновление / Предупреждение

Это решение может привести к некоторой головной боли.data.columns.codes (формально известный как data.columns.labels) не обязательно входит в порядке возрастания от read_excel(), например, может произойти FrozenList([[3, 3, 2, 2, 1, 1, 0, 0], [1, 0, 1, 0, 1, 0, 1, 0]]).При использовании подхода .from_product() здесь это вызовет проблемы и изменит порядок имен столбцов ... Обходной путь - сохранить его состояние и записать его обратно после действия:

old_col_codes = df.columns.codes
df.columns = pd.MultiIndex.from_product([c.astype(str).unique() for c in df.columns.levels])
df.columns.set_codes(old_df_codes, inplace=True)
...