Renommer l'index Pandas DataFrame

142

J'ai un fichier csv sans en-tête, avec un index DateTime. Je veux renommer l'index et le nom de la colonne, mais avec df.rename (), seul le nom de la colonne est renommé. Punaise? Je suis sur la version 0.12.0

In [2]: df = pd.read_csv(r'D:\Data\DataTimeSeries_csv//seriesSM.csv', header=None, parse_dates=[[0]], index_col=[0] )

In [3]: df.head()
Out[3]: 
                   1
0                   
2002-06-18  0.112000
2002-06-22  0.190333
2002-06-26  0.134000
2002-06-30  0.093000
2002-07-04  0.098667

In [4]: df.rename(index={0:'Date'}, columns={1:'SM'}, inplace=True)

In [5]: df.head()
Out[5]: 
                  SM
0                   
2002-06-18  0.112000
2002-06-22  0.190333
2002-06-26  0.134000
2002-06-30  0.093000
2002-07-04  0.098667
Mattijn
la source
5
Pour ceux qui viendront à cette question en 2017, cochez cette réponse ci-dessous pour voir une explication très détaillée de la rename_axisméthode.
Ted Petrou
3
Et pour ceux qui ne peuvent pas être dérangés de lire toute la bonne réponse ci-dessous, alors la solution rapide est df.rename_axis("Date", axis='index', inplace=True)selon la documentation pandas.pydata.org/pandas-docs/stable/generated/… oudf.index.names = ['Date']
tommy.carstensen

Réponses:

237

La renameméthode prend un dictionnaire pour l'index qui s'applique aux valeurs d' index .
Vous souhaitez renommer le nom du niveau d'index:

df.index.names = ['Date']

Une bonne façon de penser à cela est que les colonnes et l'index sont le même type d'objet ( Indexou MultiIndex), et que vous pouvez échanger les deux via transpose.

C'est un peu déroutant car les noms d'index ont une signification similaire à celle des colonnes, voici donc quelques exemples supplémentaires:

In [1]: df = pd.DataFrame([[1, 2, 3], [4, 5 ,6]], columns=list('ABC'))

In [2]: df
Out[2]: 
   A  B  C
0  1  2  3
1  4  5  6

In [3]: df1 = df.set_index('A')

In [4]: df1
Out[4]: 
   B  C
A      
1  2  3
4  5  6

Vous pouvez voir le changement de nom sur l'index, ce qui peut changer la valeur 1:

In [5]: df1.rename(index={1: 'a'})
Out[5]: 
   B  C
A      
a  2  3
4  5  6

In [6]: df1.rename(columns={'B': 'BB'})
Out[6]: 
   BB  C
A       
1   2  3
4   5  6

En renommant les noms de niveau:

In [7]: df1.index.names = ['index']
        df1.columns.names = ['column']

Remarque: cet attribut est juste une liste et vous pouvez le renommer en tant que compréhension / carte de liste.

In [8]: df1
Out[8]: 
column  B  C
index       
1       2  3
4       5  6
Andy Hayden
la source
2
Très bonne réponse. Juste un doux rappel que sans "inplace =True", df1.renamene changerait vraiment rien.
Sarah le
63

La réponse actuellement sélectionnée ne mentionne pas la rename_axisméthode qui peut être utilisée pour renommer les niveaux d'index et de colonne.


Pandas a une certaine bizarrerie lorsqu'il s'agit de renommer les niveaux de l'index. Il existe également une nouvelle méthode DataFrame rename_axisdisponible pour modifier les noms de niveau d'index.

Jetons un œil à un DataFrame

df = pd.DataFrame({'age':[30, 2, 12],
                       'color':['blue', 'green', 'red'],
                       'food':['Steak', 'Lamb', 'Mango'],
                       'height':[165, 70, 120],
                       'score':[4.6, 8.3, 9.0],
                       'state':['NY', 'TX', 'FL']},
                       index = ['Jane', 'Nick', 'Aaron'])

entrez la description de l'image ici

Ce DataFrame a un niveau pour chacun des index de ligne et de colonne. L'index de ligne et de colonne n'a pas de nom. Modifions le nom du niveau d'index de ligne en «noms».

df.rename_axis('names')

entrez la description de l'image ici

La rename_axisméthode a également la possibilité de modifier les noms de niveau de colonne en modifiant le axisparamètre:

df.rename_axis('names').rename_axis('attributes', axis='columns')

entrez la description de l'image ici

Si vous définissez l'index avec certaines des colonnes, le nom de la colonne deviendra le nouveau nom de niveau d'index. Ajoutons aux niveaux d'indexation de notre DataFrame d'origine:

df1 = df.set_index(['state', 'color'], append=True)
df1

entrez la description de l'image ici

Remarquez que l'index d'origine n'a pas de nom. Nous pouvons toujours utiliser rename_axismais devons lui transmettre une liste de la même longueur que le nombre de niveaux d'index.

df1.rename_axis(['names', None, 'Colors'])

entrez la description de l'image ici

Vous pouvez utiliser Nonepour supprimer efficacement les noms de niveau d'index.


Les séries fonctionnent de la même manière mais avec quelques différences

Créons une série avec trois niveaux d'index

s = df.set_index(['state', 'color'], append=True)['food']
s

       state  color
Jane   NY     blue     Steak
Nick   TX     green     Lamb
Aaron  FL     red      Mango
Name: food, dtype: object

Nous pouvons utiliser de la rename_axismême manière que nous l'avons fait avec DataFrames

s.rename_axis(['Names','States','Colors'])

Names  States  Colors
Jane   NY      blue      Steak
Nick   TX      green      Lamb
Aaron  FL      red       Mango
Name: food, dtype: object

Notez qu'il y a un élément supplémentaire de métadonnées sous la série appelée Name. Lors de la création d'une série à partir d'un DataFrame, cet attribut est défini sur le nom de la colonne.

Nous pouvons passer un nom de chaîne à la renameméthode pour le changer

s.rename('FOOOOOD')

       state  color
Jane   NY     blue     Steak
Nick   TX     green     Lamb
Aaron  FL     red      Mango
Name: FOOOOOD, dtype: object

Les DataFrames n'ont pas cet attribut et en fait lèveront une exception s'ils sont utilisés comme ceci

df.rename('my dataframe')
TypeError: 'str' object is not callable

Avant pandas 0.21, vous auriez pu rename_axisrenommer les valeurs de l'index et des colonnes. Il est obsolète, alors ne le faites pas

Ted Petrou
la source
1
Devriez-vous échanger df1 = df.set_index(['state', 'color'], append=True)avec df1.rename_axis(['names', None, 'Colors'])?
salhin
Et si je veux renommer "Nick" en "Nicolas"? C'est ce que je cherchais lorsque j'ai recherché sur Google "renommer les pandas index" et que je me suis retrouvé ici. EDIT: Oh attendez, la réponse acceptée explique cela, ce n'était tout simplement pas évident pour moi au début.
Ben Farmer
Bien, c'est la seule réponse qui peut être utilisée dans les missions enchaînées!
IanS
19

Pour les pandasversions plus récentes

df.index = df.index.rename('new name')

ou

df.index.rename('new name', inplace=True)

Ce dernier est requis si une trame de données doit conserver toutes ses propriétés.

Serge Stroobandt
la source
18

Dans Pandas version 0.13 et supérieure, les noms de niveau d'index sont immuables (type FrozenList) et ne peuvent plus être définis directement. Vous devez d'abord utiliser Index.rename()pour appliquer les nouveaux noms de niveau d'index à l'index, puis utiliser DataFrame.reindex()pour appliquer le nouvel index au DataFrame. Exemples:

Pour la version Pandas <0.13

df.index.names = ['Date']

Pour la version Pandas> = 0.13

df = df.reindex(df.index.rename(['Date']))
David Smith
la source
9
Pas vrai! Dans ma version de Pandas (0.13.1), df.index.names = ['foo'] fonctionne très bien!
LondonRob
5
Merci d'avoir remarqué que @LondonRob - `df.index.names = ['foo']` fonctionne aussi pour moi avec Pandas 0.14. Apparemment, cela n'a été brisé que brièvement et inclus lorsque je l'ai testé.
David Smith
1
La définition des noms pour l'un indexou l' autre ou columndirectement change les deux pour moi (sur Pandas 0.19), mais pas avec cette méthode.
FooBar
8

Vous pouvez également utiliser Index.set_namescomme suit:

In [25]: x = pd.DataFrame({'year':[1,1,1,1,2,2,2,2],
   ....:                   'country':['A','A','B','B','A','A','B','B'],
   ....:                   'prod':[1,2,1,2,1,2,1,2],
   ....:                   'val':[10,20,15,25,20,30,25,35]})

In [26]: x = x.set_index(['year','country','prod']).squeeze()

In [27]: x
Out[27]: 
year  country  prod
1     A        1       10
               2       20
      B        1       15
               2       25
2     A        1       20
               2       30
      B        1       25
               2       35
Name: val, dtype: int64
In [28]: x.index = x.index.set_names('foo', level=1)

In [29]: x
Out[29]: 
year  foo  prod
1     A    1       10
           2       20
      B    1       15
           2       25
2     A    1       20
           2       30
      B    1       25
           2       35
Name: val, dtype: int64
LondresRob
la source
2
Cela peut-il fonctionner pour un multiIndex? MultiIndex(levels=[['A', 'B', 'C', 'D', 'E', 'F'], ['Y', 'Z']], labels=[[0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5], [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]], names=['Portfolio', None])Est-il possible de renommer le Noneen measures?
ctrl-alt-delete
2

Si vous souhaitez utiliser le même mappage pour renommer les colonnes et l'index, vous pouvez faire:

mapping = {0:'Date', 1:'SM'}
df.index.names = list(map(lambda name: mapping.get(name, name), df.index.names))
df.rename(columns=mapping, inplace=True)
Danio
la source
0
df.index.rename('new name', inplace=True)

Est le seul qui fait le travail pour moi (pandas 0.22.0).
Sans inplace = True, le nom de l'index n'est pas défini dans mon cas.

Jan H.
la source
0

vous pouvez utiliser indexet les columnsattributs de pandas.DataFrame. REMARQUE: le nombre d'éléments de la liste doit correspondre au nombre de lignes / colonnes.

#       A   B   C
# ONE   11  12  13
# TWO   21  22  23
# THREE 31  32  33

df.index = [1, 2, 3]
df.columns = ['a', 'b', 'c']
print(df)

#     a   b   c
# 1  11  12  13
# 2  21  22  23
# 3  31  32  33
nucsit026
la source