2013-05-16 30 views
5

Mam dataframe pandy, której indeksy wyglądać następująco:wskaźnik zmiany nazwy z dataframe pandy

df.index 
['a_1', 'b_2', 'c_3', ... ] 

Chcę zmienić nazwę tych indeksów do:

['a', 'b', 'c', ... ] 

Jak mogę to zrobić bez określania słownika z jawnymi kluczami dla każdej wartości indeksu?
Próbowałem:

df.rename(index = lambda x: x.split('_')[0]) 

ale to rzuca się błąd:

AssertionError: New axis must be unique to rename 

Odpowiedz

3

To błąd można dostać, jeśli funkcja produkowane zduplikowane wartości indeksu:

>>> df = pd.DataFrame(np.random.random((4,3)),index="a_1 b_2 c_3 c_4".split()) 
>>> df 
      0   1   2 
a_1 0.854839 0.830317 0.046283 
b_2 0.433805 0.629118 0.702179 
c_3 0.390390 0.374232 0.040998 
c_4 0.667013 0.368870 0.637276 
>>> df.rename(index=lambda x: x.split("_")[0]) 
[...] 
AssertionError: New axis must be unique to rename 

jeśli naprawdę tego chcę, użyłbym kompilacji listy:

>>> df.index = [x.split("_")[0] for x in df.index] 
>>> df 
      0   1   2 
a 0.854839 0.830317 0.046283 
b 0.433805 0.629118 0.702179 
c 0.390390 0.374232 0.040998 
c 0.667013 0.368870 0.637276 

ale zastanowiłabym się, czy to naprawdę właściwy kierunek.

+0

dzięki, błąd większy sens teraz. – user1486457

5

Może masz najlepsze z obu światów za pomocą MultiIndex:

import numpy as np 
import pandas as pd 
df = pd.DataFrame(np.arange(8).reshape(4,2), index=['a_1', 'b_2', 'c_3', 'c_4']) 
print(df) 
#  0 1 
# a_1 0 1 
# b_2 2 3 
# c_3 4 5 
# c_4 6 7 

index = pd.MultiIndex.from_tuples([item.split('_') for item in df.index]) 
df.index = index 
print(df) 
#  0 1 
# a 1 0 1 
# b 2 2 3 
# c 3 4 5 
# 4 6 7 

W ten sposób można uzyskać dostęp do rzeczy, zgodnie z pierwszym poziomem indeksu:

In [30]: df.ix['c'] 
Out[30]: 
    0 1 
3 4 5 
4 6 7 

lub według oba poziomy indeksu:

In [31]: df.ix[('c','3')] 
Out[31]: 
0 4 
1 5 
Name: (c, 3) 

Co więcej, wszystkie metody DataFrame zostały stworzone do pracy w ith DataFrames z MultiIndices, więc nic nie tracisz.

Jednakże, jeśli naprawdę chcesz usunąć drugi poziom indeksu, można to zrobić:

df.reset_index(level=1, drop=True, inplace=True) 
print(df) 
# 0 1 
# a 0 1 
# b 2 3 
# c 4 5 
# c 6 7