2016-11-07 2 views
3

Я хочу найти способ изменить имя определенного столбца в многоуровневом фрейме.Pandas: изменение имени конкретного столбца в dataframe с многоуровневыми столбцами

С помощью этих данных:

data = { 
    ('A', '1', 'I'): [1, 2, 3, 4, 5], 
    ('B', '2', 'II'): [1, 2, 3, 4, 5], 
    ('C', '3', 'I'): [1, 2, 3, 4, 5], 
    ('D', '4', 'II'): [1, 2, 3, 4, 5], 
    ('E', '5', 'III'): [1, 2, 3, 4, 5], 
} 

dataDF = pd.DataFrame(data) 

Этот код не работает:

dataDF.rename(columns = {('A', '1', 'I'):('Z', '100', 'Z')}, inplace=True) 

Результат:

A B C D E 
    1 2 3 4 5 
    I II I II III 
0 1 1 1 1 1 
1 2 2 2 2 2 
2 3 3 3 3 3 
3 4 4 4 4 4 
4 5 5 5 5 5 

А также нет:

dataDF.columns.values[0] = ('Z', '100', 'Z') 

Результат:

A B C D E 
    1 2 3 4 5 
    I II I II III 
0 1 1 1 1 1 
1 2 2 2 2 2 
2 3 3 3 3 3 
3 4 4 4 4 4 
4 5 5 5 5 5 

Но с комбинацией вышеуказанных кодов, работающих !!!

dataDF.columns.values[0] = ('Z', '100', 'Z') 
dataDF.rename(columns = {('A', '1', 'I'):('Z', '100', 'Z')}, inplace=True) 
dataDF 

Результат:

Z B C D E 
    100 2 3 4 5 
    Z II I II III 
0 1 1 1 1 1 
1 2 2 2 2 2 
2 3 3 3 3 3 
3 4 4 4 4 4 
4 5 5 5 5 5 

Является ли это ошибка панд?

ответ

4

Это моя теория

панды не хочет pd.Index s быть изменяемым. Мы можем увидеть это, если мы попытаемся изменить первый элемент индекса сами

dataDF.columns[0] = ('Z', '100', 'Z') 
--------------------------------------------------------------------------- 
TypeError         Traceback (most recent call last) 
<ipython-input-32-2c0b76762235> in <module>() 
----> 1 dataDF.columns[0] = ('Z', '100', 'Z') 

//anaconda/envs/3.5/lib/python3.5/site-packages/pandas/indexes/base.py in __setitem__(self, key, value) 
    1372 
    1373  def __setitem__(self, key, value): 
-> 1374   raise TypeError("Index does not support mutable operations") 
    1375 
    1376  def __getitem__(self, key): 

TypeError: Index does not support mutable operations 

Но панды не может контролировать то, что вы делаете атрибут values.

dataDF.columns.values[0] = ('Z', '100', 'Z') 

мы видим, что dataDF.columns выглядит так же, но dataDF.columns.values четко отражает изменение. К сожалению, df.columns.values - это не то, что отображается на дисплее кадра данных.


С другой стороны, это действительно похоже, что он должен работать. Тот факт, что это не кажется мне неправильным.

dataDF.rename(columns={('A', '1', 'I'): ('Z', '100', 'Z')}, inplace=True) 

Я считаю, что причина это работает только после изменения значения, что rename вынуждает реконструкцию колонн, глядя на значения. Поскольку мы меняем значения, он теперь работает. Это исключительно kludgy, и я не рекомендую строить процесс, который опирается на это.


моя рекомендация

  • определить местоположение имени столбца вы хотите изменить
  • присвойте имя столбца в массиве значений
  • строить новые столбцы с нуля, в явной форме

from_col = ('A', '1', 'I') 
to_col = ('Z', '100', 'Z') 
colloc = dataDF.columns.get_loc(from_col) 
cvals = dataDF.columns.values 
cvals[colloc] = to_col 

dataDF.columns = pd.MultiIndex.from_tuples(cvals.tolist()) 

dataDF 

[![enter code here][1]][1] 
+0

спасибо за ваше объяснение! –

+0

приветствуются – piRSquared

0

Вы можете просто изменить его, как DF.columns.levels=[[u'Z', u'B', u'C', u'D', u'E'],[u'5', u'2', u'3', u'4', u'5'],[u'IIIIII', u'II', u'III']]

+0

все еще я не уверен, если его ошибка как ваше высказывание. –

+0

спасибо за ваше объяснение! –

Смежные вопросы