Как заменить строку в мультииндексе панд?

1

У меня есть dataframe с большим multiindex, полученным из огромного количества файлов csv. Некоторые из этих файлов имеют ошибки в различных ярлыках, т.е. "Окно" пропущено как "winZZw", что вызывает проблемы при выборе всех окон с помощью df.xs('window', level='middle', axis=1).

Поэтому мне нужно просто заменить winZZw на window.

Здесь очень минимальный образец df: (позволяет предположить данные и 'roof', 'window'… строки исходят из некоторого запутанного текстового считывателя)

header = pd.MultiIndex.from_product(['roof', 'window', 'basement'], names = ['top', 'middle', 'bottom'])
dates = pd.date_range('01/01/2000','01/12/2010', freq='MS')
data = np.random.randn(len(dates))
df = pd.DataFrame(data, index=dates, columns=header)
header2 = pd.MultiIndex.from_product(['roof', 'winZZw', 'basement'], names = ['top', 'middle', 'bottom'])
data = 3*(np.random.randn(len(dates)))
df2 = pd.DataFrame(data, index=dates, columns=header2)
df = pd.concat([df, df2], axis=1)
header3 = pd.MultiIndex.from_product(['roof', 'door', 'basement'], names = ['top', 'middle', 'bottom'])
data = 2*(np.random.randn(len(dates)))
df3 = pd.DataFrame(data, index=dates, columns=header3)
df = pd.concat([df, df3], axis=1)

Теперь я хочу, чтобы xs новый dataframe для всех домов, у которых есть окно на их среднем уровне: windf = df.xs('window', level='middle', axis=1)

Но это явно пропускает опечатанную winZZw.

Итак, как я заменю winZZw на window?

Единственный способ, которым я нашел, - использовать set_levels, но если бы я правильно понял это, мне нужно было бы его полностью загрузить, т.е.

df.columns.set_levels([u'window',u'window', u'door'], level='middle',inplace=True)

но это имеет два вопроса:

  • Мне нужно передать весь индекс, что легко в этом примере, но невозможно/глупо для тысячи столбцов df с сотнями ярлыков.
  • Кажется, что этот список нужен назад (теперь мой первый вход в df имеет дверь посередине, а не окно). Вероятно, это может быть исправлено, но кажется странным

Я могу работать вокруг этих вопросов xs ИНГ нового ФРА только winZZw s, а затем устанавливающего уровни с set_levels(df.shape[1]*[u'window'], level='middle'), а затем concatting вместе опять же, но я хотел бы иметь что-то более прямое аналоговое для str.replace('winZZw', 'window'), но я не могу понять, как это сделать.

  • 0
    Кажется, код содержит ошибку, пожалуйста, проверьте сначала. MultiIndex.from_product требует список списка в качестве входных данных.
  • 0
    В ответе @jezraels он изменил ['roof', 'window', 'basement'] на [['roof'],[ 'window'], ['basement']] чтобы он работал. Так что, возможно, вы используете слишком старые панды.
Показать ещё 1 комментарий
Теги:
pandas
dataframe
indexing

1 ответ

0
Лучший ответ

Используйте rename с указанием уровня:

header = pd.MultiIndex.from_product([['roof'],[ 'window'], ['basement']], names = ['top', 'middle', 'bottom'])
dates = pd.date_range('01/01/2000','01/12/2010', freq='MS')
data = np.random.randn(len(dates))
df = pd.DataFrame(data, index=dates, columns=header)
header2 = pd.MultiIndex.from_product([['roof'], ['winZZw'], ['basement']], names = ['top', 'middle', 'bottom'])
data = 3*(np.random.randn(len(dates)))
df2 = pd.DataFrame(data, index=dates, columns=header2)
df = pd.concat([df, df2], axis=1)
header3 = pd.MultiIndex.from_product([['roof'], ['door'], ['basement']], names = ['top', 'middle', 'bottom'])
data = 2*(np.random.randn(len(dates)))
df3 = pd.DataFrame(data, index=dates, columns=header3)
df = pd.concat([df, df3], axis=1)

df = df.rename(columns={'winZZw':'window'}, level='middle')
print(df.head())

top             roof                    
middle        window                door
bottom      basement  basement  basement
2000-01-01 -0.131052 -1.189049  1.310137
2000-02-01 -0.200646  1.893930  2.124765
2000-03-01 -1.690123 -2.128965  1.639439
2000-04-01 -0.794418  0.605021 -2.810978
2000-05-01  1.528002 -0.286614  0.736445
  • 0
    Признаюсь, я забыл протестировать его с примером, так как он потерпел неудачу с TypeError: rename() got an unexpected keyword argument "level" в моих реальных данных, который, казалось, указывал мне, что rename просто не может работать с индексом.
  • 0
    @JC_CL - Какая у тебя версия для панд? Требуется 0.20.0+ - отметьте Добавление ключевого слова уровня в DataFrame / Series.rename, чтобы переименовать метки на указанном уровне MultiIndex.
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню