Renommer des colonnes dans les pandas


1830

J'ai un DataFrame utilisant des pandas et des étiquettes de colonne que je dois modifier pour remplacer les étiquettes de colonne d'origine.

Je voudrais changer les noms de colonnes dans un DataFrame Aoù les noms de colonnes d'origine sont:

['$a', '$b', '$c', '$d', '$e'] 

à

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

J'ai les noms de colonnes modifiés stockés dans une liste, mais je ne sais pas comment remplacer les noms de colonnes.


1
Vous voudrez peut-être aller consulter les documents officiels qui couvrent le changement de nom des étiquettes de colonne: pandas.pydata.org/pandas-docs/stable/user_guide/text.html
ccpizza

Réponses:


1832

Attribuez-le simplement à l' .columnsattribut:

>>> df = pd.DataFrame({'$a':[1,2], '$b': [10,20]})
>>> df.columns = ['a', 'b']
>>> df
   a   b
0  1  10
1  2  20

303
Est-il possible de modifier un nom d'en-tête de colonne unique?
ericmjl

112
@ericmjl: supposons que vous vouliez changer le nom de la première variable de df. Ensuite, vous pouvez faire quelque chose comme:new_columns = df.columns.values; new_columns[0] = 'XX'; df.columns = new_columns
cd98

54
On dirait que vous auriez pu simplement faire df.columns.values ​​[0] = 'XX'
RAY

25
Je plaisante, @RAY - ne fais pas ça. On dirait que c'est une liste générée indépendamment de l'indexation qui stocke le nom de la colonne. Est-ce un bon travail de détruire le nom des colonnes pour votre df ...
Mitch Flax

433
@ericmjl yesdf.rename(columns = {'$b':'B'}, inplace = True)
nachocab

2850

RENOMMER DES COLONNES SPÉCIFIQUES

Utilisez la df.rename()fonction et référez-vous aux colonnes à renommer. Toutes les colonnes ne doivent pas être renommées:

df = df.rename(columns={'oldName1': 'newName1', 'oldName2': 'newName2'})
# Or rename the existing DataFrame (rather than creating a copy) 
df.rename(columns={'oldName1': 'newName1', 'oldName2': 'newName2'}, inplace=True)

Exemple de code minimal

df = pd.DataFrame('x', index=range(3), columns=list('abcde'))
df

   a  b  c  d  e
0  x  x  x  x  x
1  x  x  x  x  x
2  x  x  x  x  x

Les méthodes suivantes fonctionnent toutes et produisent la même sortie:

df2 = df.rename({'a': 'X', 'b': 'Y'}, axis=1)  # new method
df2 = df.rename({'a': 'X', 'b': 'Y'}, axis='columns')
df2 = df.rename(columns={'a': 'X', 'b': 'Y'})  # old method  

df2

   X  Y  c  d  e
0  x  x  x  x  x
1  x  x  x  x  x
2  x  x  x  x  x

N'oubliez pas de réattribuer le résultat, car la modification n'est pas en place. Vous pouvez également spécifier inplace=True:

df.rename({'a': 'X', 'b': 'Y'}, axis=1, inplace=True)
df

   X  Y  c  d  e
0  x  x  x  x  x
1  x  x  x  x  x
2  x  x  x  x  x

À partir de la version 0.25, vous pouvez également spécifier errors='raise'de générer des erreurs si une colonne à renommer non valide est spécifiée. Voir les documents v0.25rename() .


RÉASSIGNER LES EN-TÊTES DE COLONNE

Utilisez df.set_axis()avec axis=1et inplace=False(pour renvoyer une copie).

df2 = df.set_axis(['V', 'W', 'X', 'Y', 'Z'], axis=1, inplace=False)
df2

   V  W  X  Y  Z
0  x  x  x  x  x
1  x  x  x  x  x
2  x  x  x  x  x

Cela renvoie une copie, mais vous pouvez modifier le DataFrame sur place en définissant inplace=True(il s'agit du comportement par défaut pour les versions <= 0,24, mais il est susceptible de changer à l'avenir).

Vous pouvez également affecter directement des en-têtes:

df.columns = ['V', 'W', 'X', 'Y', 'Z']
df

   V  W  X  Y  Z
0  x  x  x  x  x
1  x  x  x  x  x
2  x  x  x  x  x

2
quand je le fais avec une trame de données 6 colonne (dataframe <appuyez sur Entrée>) la représentation abrégée: code<class « pandas.core.frame.DataFrame »> Int64Index: 1000 entrées, 0 à 999 colonnes de données: BodyMarkdown 1000 non nuls codetravaux , mais quand je fais dataframe.head () les anciens noms des colonnes réapparaissent.
darKoram

12
Je suis redouté SettingWithCopyWarning:lorsque j'utilise le deuxième extrait de code dans cette réponse.
Monica Heddneck

y a-t-il une version de ceci avec le remplacement regex?
denfromufa

@lexual Et si deux colonnes existantes ont le même nom? Comment faire référence à l'ancien nom de colonne?
vagabond

14
La première solution: df = df.rename(columns={'oldName1': 'newName1', 'oldName2': 'newName2'})modifie le nom affiché, mais pas les éléments de la structure de données sous-jacente. Donc, si vous essayez, df['newName1']vous obtiendrez une erreur. Il inplace=Trueest nécessaire d'éviter ce gotchya.
irritable_phd_syndrom

402

La renameméthode peut prendre une fonction , par exemple:

In [11]: df.columns
Out[11]: Index([u'$a', u'$b', u'$c', u'$d', u'$e'], dtype=object)

In [12]: df.rename(columns=lambda x: x[1:], inplace=True)

In [13]: df.columns
Out[13]: Index([u'a', u'b', u'c', u'd', u'e'], dtype=object)

56
Agréable. Celui-ci m'a sauvé la journée:df.rename(columns=lambda x: x.lstrip(), inplace=True)
root-11

2
Semblable à @ root-11 - dans mon cas, il y avait un caractère de puce qui n'était pas imprimé dans la sortie de la console IPython, donc je devais supprimer plus que des espaces blancs (bande), donc:t.columns = t.columns.str.replace(r'[^\x00-\x7F]+','')
The Red Pea

9
df.rename(columns=lambda x: x.replace(' ', '_'), inplace=True)est un joyau pour que nous puissions écrire df.Column_1_Nameau lieu d'écrire df.loc[:, 'Column 1 Name'].
Little Bobby Tables


164

Pandas 0.21+ Réponse

Il y a eu quelques mises à jour importantes pour renommer les colonnes dans la version 0.21.

  • La renameméthode a ajouté le axisparamètre qui peut être défini sur columnsou 1. Cette mise à jour rend cette méthode compatible avec le reste de l'API pandas. Il a toujours les paramètres indexet columnsmais vous n'êtes plus obligé de les utiliser.
  • La set_axisméthode avec l' inplaceensemble Falsevous permet de renommer toutes les étiquettes d'index ou de colonne avec une liste.

Exemples pour Pandas 0.21+

Construisez un exemple de DataFrame:

df = pd.DataFrame({'$a':[1,2], '$b': [3,4], 
                   '$c':[5,6], '$d':[7,8], 
                   '$e':[9,10]})

   $a  $b  $c  $d  $e
0   1   3   5   7   9
1   2   4   6   8  10

Utilisation renameavec axis='columns'ouaxis=1

df.rename({'$a':'a', '$b':'b', '$c':'c', '$d':'d', '$e':'e'}, axis='columns')

ou

df.rename({'$a':'a', '$b':'b', '$c':'c', '$d':'d', '$e':'e'}, axis=1)

Les deux aboutissent à ce qui suit:

   a  b  c  d   e
0  1  3  5  7   9
1  2  4  6  8  10

Il est toujours possible d'utiliser l'ancienne signature de méthode:

df.rename(columns={'$a':'a', '$b':'b', '$c':'c', '$d':'d', '$e':'e'})

La renamefonction accepte également les fonctions qui seront appliquées à chaque nom de colonne.

df.rename(lambda x: x[1:], axis='columns')

ou

df.rename(lambda x: x[1:], axis=1)

Utilisation set_axisavec une liste etinplace=False

Vous pouvez fournir à la set_axisméthode une liste dont la longueur est égale au nombre de colonnes (ou index). Actuellement, la valeur par inplacedéfaut est True, mais inplacesera définie par défaut Falsedans les versions futures.

df.set_axis(['a', 'b', 'c', 'd', 'e'], axis='columns', inplace=False)

ou

df.set_axis(['a', 'b', 'c', 'd', 'e'], axis=1, inplace=False)

Pourquoi ne pas utiliser df.columns = ['a', 'b', 'c', 'd', 'e']?

Il n'y a rien de mal à affecter directement des colonnes comme celle-ci. C'est une très bonne solution.

L'avantage de l'utilisation set_axisest qu'elle peut être utilisée dans le cadre d'une chaîne de méthodes et qu'elle renvoie une nouvelle copie du DataFrame. Sans cela, vous devrez stocker vos étapes intermédiaires de la chaîne dans une autre variable avant de réaffecter les colonnes.

# new for pandas 0.21+
df.some_method1()
  .some_method2()
  .set_axis()
  .some_method3()

# old way
df1 = df.some_method1()
        .some_method2()
df1.columns = columns
df1.some_method3()

1
Merci pour le Pandas 0.21+ answer- en quelque sorte j'ai raté cette partie dans la partie "quoi de neuf" ...
MaxU

1
La solution ne semble pas fonctionner pour Pandas 3.6: df.rename ({'$ a': 'a', '$ b': 'b', '$ c': 'c', '$ d': 'd ',' $ e ':' e '}, axis =' colonnes '). Obtient un argument de mot clé inattendu "axe"
Arthur D. Howland

3
df.columns = ['a', 'b', 'c', 'd', 'e'] ne semble plus fonctionner, en travaillant avec la version 0.22 J'ai un avertissement disant que Pandas n'autorise pas la création de colonnes via un nouveau nom d'attribut . comment renommer si toutes mes colonnes sont appelées de la même façon: /
Nabla

Existe-t-il un moyen de renommer une, plusieurs ou toutes les colonnes, si vous ne connaissez pas le nom de la ou des colonnes au préalable mais uniquement leur index? Merci!
tommy.carstensen

ce fut un commentaire très utile. par exemple, la fonction lambda a répondu à ma question sur la façon de faire ce qui suit:(df .groupby(['page',pd.Grouper(key='date',freq='MS')])['clicks'].sum() .unstack(1) .rename(lambda x: x.strftime("%Y-%m"), axis='columns') )
mesureallthethings

131

Étant donné que vous souhaitez uniquement supprimer le signe $ dans tous les noms de colonne, vous pouvez simplement faire:

df = df.rename(columns=lambda x: x.replace('$', ''))

OU

df.rename(columns=lambda x: x.replace('$', ''), inplace=True)

1
Celui-ci aide non seulement dans le cas de l'OP mais aussi dans les exigences génériques. Par exemple: pour diviser un nom de colonne par un séparateur et en utiliser une partie.
Deepak


61
old_names = ['$a', '$b', '$c', '$d', '$e'] 
new_names = ['a', 'b', 'c', 'd', 'e']
df.rename(columns=dict(zip(old_names, new_names)), inplace=True)

De cette façon, vous pouvez modifier manuellement le new_namescomme vous le souhaitez. Fonctionne très bien lorsque vous devez renommer seulement quelques colonnes pour corriger les fautes d'orthographe, les accents, supprimer les caractères spéciaux, etc.


1
J'aime cette approche, mais je pense que df.columns = ['a', 'b', 'c', 'd', 'e']c'est plus simple.
Christopher Pearson

1
J'aime cette méthode pour compresser les anciens et les nouveaux noms. Nous pouvons utiliser df.columns.valuespour obtenir les anciens noms.
bkowshik

1
J'affiche la vue tabulaire et copie les colonnes dans old_names. Je copie le tableau des exigences dans new_names. Utilisez ensuite dict (zip (old_names, new_names)). Solution très élégante.
mythicalcoder

J'utilise souvent des sous-ensembles de listes de quelque chose comme myList = list(df) myList[10:20]:, etc - donc c'est parfait.
Tim Gottgetreu

Mieux vaut prendre les anciens noms comme l'a suggéré @bkowshik, puis les modifier et les réinsérer, c'est-à-dire namez = df.columns.valuessuivis de quelques modifications, ensuite df.columns = namez.
pauljohn32

34

Solutions en ligne ou en pipeline

Je vais me concentrer sur deux choses:

  1. OP indique clairement

    J'ai les noms de colonnes modifiés stockés dans une liste, mais je ne sais pas comment remplacer les noms de colonnes.

    Je ne veux pas résoudre le problème de la façon de remplacer '$'ou de supprimer le premier caractère de chaque en-tête de colonne. OP a déjà fait cette étape. Au lieu de cela, je veux me concentrer sur le remplacement de l' columnsobjet existant par un nouveau étant donné une liste de noms de colonnes de remplacement.

  2. df.columns = newnewest la liste des nouveaux noms de colonnes est aussi simple que possible. L'inconvénient de cette approche est qu'elle nécessite la modification de l'attribut du cadre de données existant columnset qu'elle n'est pas effectuée en ligne. Je vais montrer quelques façons d'effectuer cela via le pipelining sans modifier le cadre de données existant.


Configuration 1
Pour me concentrer sur la nécessité de renommer les noms de colonne de remplacement par une liste préexistante, je vais créer un nouvel exemple de trame dfde données avec les noms de colonne initiaux et les nouveaux noms de colonne non liés.

df = pd.DataFrame({'Jack': [1, 2], 'Mahesh': [3, 4], 'Xin': [5, 6]})
new = ['x098', 'y765', 'z432']

df

   Jack  Mahesh  Xin
0     1       3    5
1     2       4    6

Solution 1
pd.DataFrame.rename

Il a déjà été dit que si vous aviez un dictionnaire mappant les anciens noms de colonne aux nouveaux noms de colonne, vous pourriez utiliser pd.DataFrame.rename.

d = {'Jack': 'x098', 'Mahesh': 'y765', 'Xin': 'z432'}
df.rename(columns=d)

   x098  y765  z432
0     1     3     5
1     2     4     6

Cependant, vous pouvez facilement créer ce dictionnaire et l'inclure dans l'appel à rename. Ce qui suit tire parti du fait que lors de l'itération df, nous itérons sur chaque nom de colonne.

# given just a list of new column names
df.rename(columns=dict(zip(df, new)))

   x098  y765  z432
0     1     3     5
1     2     4     6

Cela fonctionne très bien si vos noms de colonnes d'origine sont uniques. Mais s'ils ne le sont pas, cela tombe en panne.


Configurer 2
colonnes non uniques

df = pd.DataFrame(
    [[1, 3, 5], [2, 4, 6]],
    columns=['Mahesh', 'Mahesh', 'Xin']
)
new = ['x098', 'y765', 'z432']

df

   Mahesh  Mahesh  Xin
0       1       3    5
1       2       4    6

Solution 2 en
pd.concat utilisant l' keysargument

Tout d'abord, notez ce qui se passe lorsque nous essayons d'utiliser la solution 1:

df.rename(columns=dict(zip(df, new)))

   y765  y765  z432
0     1     3     5
1     2     4     6

Nous n'avons pas mappé la newliste en tant que noms de colonne. Nous avons fini par répéter y765. Au lieu de cela, nous pouvons utiliser l' keysargument de la pd.concatfonction tout en parcourant les colonnes de df.

pd.concat([c for _, c in df.items()], axis=1, keys=new) 

   x098  y765  z432
0     1     3     5
1     2     4     6

Solution 3
Reconstruire. Cela ne doit être utilisé que si vous en avez un dtypepour toutes les colonnes. Sinon, vous vous retrouverez avec dtype objectpour toutes les colonnes et les reconvertir nécessite plus de travail de dictionnaire.

Célibataire dtype

pd.DataFrame(df.values, df.index, new)

   x098  y765  z432
0     1     3     5
1     2     4     6

Mixte dtype

pd.DataFrame(df.values, df.index, new).astype(dict(zip(new, df.dtypes)))

   x098  y765  z432
0     1     3     5
1     2     4     6

Solution 4
Ceci est un truc gimmicky avec transposeet set_index. pd.DataFrame.set_indexnous permet de définir un index en ligne mais il n'y a pas de correspondant set_columns. Nous pouvons donc transposer, puis set_indextransposer en arrière. Cependant, la même mise en garde unique dtypeou mixte dtypede la solution 3 s'applique ici.

Célibataire dtype

df.T.set_index(np.asarray(new)).T

   x098  y765  z432
0     1     3     5
1     2     4     6

Mixte dtype

df.T.set_index(np.asarray(new)).T.astype(dict(zip(new, df.dtypes)))

   x098  y765  z432
0     1     3     5
1     2     4     6

Solution 5
Utilisez un lambdadans pd.DataFrame.renamequi parcourt chaque élément de new
Dans cette solution, nous passons un lambda qui le prend xmais l'ignore ensuite. Cela prend aussi un ymais ne s'y attend pas. Au lieu de cela, un itérateur est donné comme valeur par défaut et je peux ensuite l'utiliser pour parcourir un à la fois sans tenir compte de la valeur de x.

df.rename(columns=lambda x, y=iter(new): next(y))

   x098  y765  z432
0     1     3     5
1     2     4     6

Et comme me l'ont fait remarquer les gens dans le chat sopython , si j'ajoute un *entre xet y, je peux protéger ma yvariable. Cependant, dans ce contexte, je ne pense pas qu'il ait besoin d'être protégé. Cela vaut encore la peine d'être mentionné.

df.rename(columns=lambda x, *, y=iter(new): next(y))

   x098  y765  z432
0     1     3     5
1     2     4     6

Peut-être que nous pouvons ajouterdf.rename(lambda x : x.lstrip('$'),axis=1)
YOBEN_S

Bonjour @piRSquared, pourriez-vous expliquer comment les pandas utilisent la fonction lambda dans la solution 5, s'il vous plaît? Je ne comprends pas très bien ce que tu veux dire quand tu dis xest ignoré?
Josmoor98

33

Noms des colonnes et noms des séries

Je voudrais expliquer un peu ce qui se passe dans les coulisses.

Les trames de données sont un ensemble de séries.

Les séries sont à leur tour une extension numpy.array

numpy.arrays ont une propriété .name

C'est le nom de la série. Il est rare que les pandas respectent cet attribut, mais il persiste par endroits et peut être utilisé pour pirater certains comportements des pandas.

Nommer la liste des colonnes

Beaucoup de réponses ici parlent de l' df.columnsattribut étant un listalors qu'en fait c'est un Series. Cela signifie qu'il a un .nameattribut.

Voici ce qui se passe si vous décidez de renseigner le nom des colonnes Series:

df.columns = ['column_one', 'column_two']
df.columns.names = ['name of the list of columns']
df.index.names = ['name of the index']

name of the list of columns     column_one  column_two
name of the index       
0                                    4           1
1                                    5           2
2                                    6           3

Notez que le nom de l'index vient toujours une colonne plus bas.

Des artefacts qui persistent

L' .nameattribut persiste parfois. Si vous définissez df.columns = ['one', 'two']alors le df.one.namesera 'one'.

Si vous vous mettez df.one.name = 'three'alors df.columnsvous donnera toujours ['one', 'two'], et df.one.namevous donnera'three'

MAIS

pd.DataFrame(df.one) reviendra

    three
0       1
1       2
2       3

Parce que les pandas réutilisent .namele déjà défini Series.

Noms de colonnes à plusieurs niveaux

Pandas a des façons de faire des noms de colonnes à plusieurs couches. Il n'y a pas tellement de magie en jeu, mais je voulais aussi couvrir cela dans ma réponse, car je ne vois personne en parler ici.

    |one            |
    |one      |two  |
0   |  4      |  1  |
1   |  5      |  2  |
2   |  6      |  3  |

Ceci est facilement réalisable en définissant des colonnes sur des listes, comme ceci:

df.columns = [['one', 'one'], ['one', 'two']]

18

Si vous avez le dataframe, df.columns vide tout dans une liste que vous pouvez manipuler puis réaffecter dans votre dataframe en tant que noms de colonnes ...

columns = df.columns
columns = [row.replace("$","") for row in columns]
df.rename(columns=dict(zip(columns, things)), inplace=True)
df.head() #to validate the output

Meilleur moyen? IDK. Un moyen - oui.

Une meilleure façon d'évaluer toutes les principales techniques proposées dans les réponses à la question est ci-dessous en utilisant cProfile pour mesurer la mémoire et le temps d'exécution. @kadee, @kaitlyn et @eumiro avaient les fonctions avec les temps d'exécution les plus rapides - bien que ces fonctions soient si rapides que nous comparons l'arrondi de .000 et .001 secondes pour toutes les réponses. Morale: ma réponse ci-dessus n'est probablement pas la «meilleure» façon.

import pandas as pd
import cProfile, pstats, re

old_names = ['$a', '$b', '$c', '$d', '$e']
new_names = ['a', 'b', 'c', 'd', 'e']
col_dict = {'$a': 'a', '$b': 'b','$c':'c','$d':'d','$e':'e'}

df = pd.DataFrame({'$a':[1,2], '$b': [10,20],'$c':['bleep','blorp'],'$d':[1,2],'$e':['texa$','']})

df.head()

def eumiro(df,nn):
    df.columns = nn
    #This direct renaming approach is duplicated in methodology in several other answers: 
    return df

def lexual1(df):
    return df.rename(columns=col_dict)

def lexual2(df,col_dict):
    return df.rename(columns=col_dict, inplace=True)

def Panda_Master_Hayden(df):
    return df.rename(columns=lambda x: x[1:], inplace=True)

def paulo1(df):
    return df.rename(columns=lambda x: x.replace('$', ''))

def paulo2(df):
    return df.rename(columns=lambda x: x.replace('$', ''), inplace=True)

def migloo(df,on,nn):
    return df.rename(columns=dict(zip(on, nn)), inplace=True)

def kadee(df):
    return df.columns.str.replace('$','')

def awo(df):
    columns = df.columns
    columns = [row.replace("$","") for row in columns]
    return df.rename(columns=dict(zip(columns, '')), inplace=True)

def kaitlyn(df):
    df.columns = [col.strip('$') for col in df.columns]
    return df

print 'eumiro'
cProfile.run('eumiro(df,new_names)')
print 'lexual1'
cProfile.run('lexual1(df)')
print 'lexual2'
cProfile.run('lexual2(df,col_dict)')
print 'andy hayden'
cProfile.run('Panda_Master_Hayden(df)')
print 'paulo1'
cProfile.run('paulo1(df)')
print 'paulo2'
cProfile.run('paulo2(df)')
print 'migloo'
cProfile.run('migloo(df,old_names,new_names)')
print 'kadee'
cProfile.run('kadee(df)')
print 'awo'
cProfile.run('awo(df)')
print 'kaitlyn'
cProfile.run('kaitlyn(df)')

Pourquoi avez-vous besoin de renommer la méthode? Quelque chose comme ça a fonctionné pour moi # df.columns = [row.replace ('$', '') pour la ligne dans df.columns]
shantanuo

Je ne comprends pas la partie «choses». Que dois-je remplacer? Les anciennes colonnes?
Andrea Ianni

18

Disons que c'est votre dataframe.

entrez la description de l'image ici

Vous pouvez renommer les colonnes à l'aide de deux méthodes.

  1. En utilisant dataframe.columns=[#list]

    df.columns=['a','b','c','d','e']

    entrez la description de l'image ici

    La limitation de cette méthode est que si une colonne doit être modifiée, la liste complète des colonnes doit être transmise. En outre, cette méthode n'est pas applicable sur les étiquettes d'index. Par exemple, si vous avez réussi ceci:

    df.columns = ['a','b','c','d']

    Cela générera une erreur. Non-concordance de longueur: l'axe prévu a 5 éléments, les nouvelles valeurs ont 4 éléments.

  2. Une autre méthode est la rename()méthode Pandas qui est utilisée pour renommer tout index, colonne ou ligne

    df = df.rename(columns={'$a':'a'})

    entrez la description de l'image ici

De même, vous pouvez modifier n'importe quelle ligne ou colonne.


17
df = pd.DataFrame({'$a': [1], '$b': [1], '$c': [1], '$d': [1], '$e': [1]})

Si votre nouvelle liste de colonnes est dans le même ordre que les colonnes existantes, l'affectation est simple:

new_cols = ['a', 'b', 'c', 'd', 'e']
df.columns = new_cols
>>> df
   a  b  c  d  e
0  1  1  1  1  1

Si vous aviez un dictionnaire composé d'anciens noms de colonne pour de nouveaux noms de colonne, vous pouvez effectuer les opérations suivantes:

d = {'$a': 'a', '$b': 'b', '$c': 'c', '$d': 'd', '$e': 'e'}
df.columns = df.columns.map(lambda col: d[col])  # Or `.map(d.get)` as pointed out by @PiRSquared.
>>> df
   a  b  c  d  e
0  1  1  1  1  1

Si vous n'avez pas de liste ou de mappage de dictionnaire, vous pouvez supprimer le $symbole de tête via une compréhension de liste:

df.columns = [col[1:] if col[0] == '$' else col for col in df]

2
Au lieu de lambda col: d[col]vous pourriez passer d.get... donc ça ressemblerait àdf.columns.map(d.get)
piRSquared


15

Comprenons le changement de nom par un petit exemple ...

1.Renommer les colonnes à l'aide du mappage:

df = pd.DataFrame({"A": [1, 2, 3], "B": [4, 5, 6]}) #creating a df with column name A and B
df.rename({"A": "new_a", "B": "new_b"},axis='columns',inplace =True) #renaming column A with 'new_a' and B with 'new_b'

output:
   new_a  new_b
0  1       4
1  2       5
2  3       6

2. Renommer l'index / Row_Name en utilisant le mappage:

df.rename({0: "x", 1: "y", 2: "z"},axis='index',inplace =True) #Row name are getting replaced by 'x','y','z'.

output:
       new_a  new_b
    x  1       4
    y  2       5
    z  3       6

La réponse la plus votée a déjà de tels exemples ...
Itamar Mushkin

14

Une autre façon de remplacer les étiquettes de colonne d'origine est de supprimer les caractères indésirables (ici «$») des étiquettes de colonne d'origine.

Cela aurait pu être fait en exécutant une boucle for sur df.columns et en ajoutant les colonnes supprimées à df.columns.

Au lieu de cela, nous pouvons le faire proprement dans une seule déclaration en utilisant la compréhension de liste comme ci-dessous:

df.columns = [col.strip('$') for col in df.columns]

(la stripméthode en Python supprime le caractère donné du début et de la fin de la chaîne.)


2
Pouvez-vous expliquer comment / pourquoi cela fonctionne? Cela rendra la réponse plus précieuse pour les futurs lecteurs.
Dan Lowe

12

Très simple à utiliser

df.columns = ['Name1', 'Name2', 'Name3'...]

et il attribuera les noms des colonnes par l'ordre dans lequel vous les avez mis


10

Vous pouvez utiliser str.slicepour cela:

df.columns = df.columns.str.slice(1)

1
PS: C'est un équivalent plus verbeux de df.columns.str[1:]... probablement mieux à utiliser, c'est plus court et plus évident.
cs95

9

Je sais que cette question et réponse a été mâchée à mort. Mais je m'en suis référé à l'inspiration pour l'un des problèmes que j'avais. J'ai pu le résoudre en utilisant des morceaux de différentes réponses, fournissant ainsi ma réponse au cas où quelqu'un en aurait besoin.

Ma méthode est générique dans laquelle vous pouvez ajouter des délimiteurs supplémentaires en séparant la delimiters=variable par une virgule et en la rendant pérenne.

Code de travail:

import pandas as pd
import re


df = pd.DataFrame({'$a':[1,2], '$b': [3,4],'$c':[5,6], '$d': [7,8], '$e': [9,10]})

delimiters = '$'
matchPattern = '|'.join(map(re.escape, delimiters))
df.columns = [re.split(matchPattern, i)[1] for i in df.columns ]

Production:

>>> df
   $a  $b  $c  $d  $e
0   1   3   5   7   9
1   2   4   6   8  10

>>> df
   a  b  c  d   e
0  1  3  5  7   9
1  2  4  6  8  10

8

Notez que ces approches ne fonctionnent pas pour un MultiIndex. Pour un MultiIndex, vous devez faire quelque chose comme ceci:

>>> df = pd.DataFrame({('$a','$x'):[1,2], ('$b','$y'): [3,4], ('e','f'):[5,6]})
>>> df
   $a $b  e
   $x $y  f
0  1  3  5
1  2  4  6
>>> rename = {('$a','$x'):('a','x'), ('$b','$y'):('b','y')}
>>> df.columns = pandas.MultiIndex.from_tuples([
        rename.get(item, item) for item in df.columns.tolist()])
>>> df
   a  b  e
   x  y  f
0  1  3  5
1  2  4  6

8

Une autre option consiste à renommer à l'aide d'une expression régulière:

import pandas as pd
import re

df = pd.DataFrame({'$a':[1,2], '$b':[3,4], '$c':[5,6]})

df = df.rename(columns=lambda x: re.sub('\$','',x))
>>> df
   a  b  c
0  1  3  5
1  2  4  6

6

Si vous devez gérer des charges de colonnes nommées par le système fournisseur hors de votre contrôle, j'ai trouvé l'approche suivante qui est une combinaison d'une approche générale et de remplacements spécifiques en une seule fois.

Créez d'abord un dictionnaire à partir des noms de colonnes de la trame de données à l'aide d'expressions regex afin de jeter certaines annexes de noms de colonnes, puis ajoutez des remplacements spécifiques au dictionnaire pour nommer les colonnes principales comme prévu plus tard dans la base de données réceptrice.

Ceci est ensuite appliqué à la trame de données en une seule fois.

dict=dict(zip(df.columns,df.columns.str.replace('(:S$|:C1$|:L$|:D$|\.Serial:L$)','')))
dict['brand_timeseries:C1']='BTS'
dict['respid:L']='RespID'
dict['country:C1']='CountryID'
dict['pim1:D']='pim_actual'
df.rename(columns=dict, inplace=True)

5

En plus de la solution déjà fournie, vous pouvez remplacer toutes les colonnes pendant que vous lisez le fichier. Nous pouvons utiliser nameset header=0pour cela.

Tout d'abord, nous créons une liste des noms que nous aimons utiliser comme noms de colonne:

import pandas as pd

ufo_cols = ['city', 'color reported', 'shape reported', 'state', 'time']
ufo.columns = ufo_cols

ufo = pd.read_csv('link to the file you are using', names = ufo_cols, header = 0)

Dans ce cas, tous les noms de colonne seront remplacés par les noms que vous avez dans votre liste.


4

Voici une petite fonction astucieuse que j'aime utiliser pour réduire la frappe:

def rename(data, oldnames, newname): 
    if type(oldnames) == str: #input can be a string or list of strings 
        oldnames = [oldnames] #when renaming multiple columns 
        newname = [newname] #make sure you pass the corresponding list of new names
    i = 0 
    for name in oldnames:
        oldvar = [c for c in data.columns if name in c]
        if len(oldvar) == 0: 
            raise ValueError("Sorry, couldn't find that column in the dataset")
        if len(oldvar) > 1: #doesn't have to be an exact match 
            print("Found multiple columns that matched " + str(name) + " :")
            for c in oldvar:
                print(str(oldvar.index(c)) + ": " + str(c))
            ind = input('please enter the index of the column you would like to rename: ')
            oldvar = oldvar[int(ind)]
        if len(oldvar) == 1:
            oldvar = oldvar[0]
        data = data.rename(columns = {oldvar : newname[i]})
        i += 1 
    return data   

Voici un exemple de son fonctionnement:

In [2]: df = pd.DataFrame(np.random.randint(0,10,size=(10, 4)), columns=['col1','col2','omg','idk'])
#first list = existing variables
#second list = new names for those variables
In [3]: df = rename(df, ['col','omg'],['first','ohmy']) 
Found multiple columns that matched col :
0: col1
1: col2

please enter the index of the column you would like to rename: 0

In [4]: df.columns
Out[5]: Index(['first', 'col2', 'ohmy', 'idk'], dtype='object')

1
Le cas d'utilisation d'une fonction comme celle-ci est extrêmement rare. Dans la plupart des cas, je sais ce que je recherche et à quoi je veux le renommer, je l'attribuerais / le modifierais moi-même.
cs95

1
@ cs95 J'ai tendance à travailler avec de grandes enquêtes nationales ou internationales où les variables auront des noms de variable codés qui commencent par des préfixes en fonction des options de réponse, des échelles de likert et des branchements (tels que EDU_2913.443, EDU_2913.421, ...). Cette fonction m'a été très utile pour travailler avec ces types d'ensembles, je comprends bien que ce n'est pas pour vous :)
seeiespi

4

Renommer des colonnes dans les pandas est une tâche facile.

df.rename(columns = {'$a':'a','$b':'b','$c':'c','$d':'d','$e':'e'},inplace = True)

2

En supposant que vous pouvez utiliser une expression régulière. Cette solution supprime le besoin d'encodage manuel à l'aide d'expressions régulières

import pandas as pd
import re

srch=re.compile(r"\w+")

data=pd.read_csv("CSV_FILE.csv")
cols=data.columns
new_cols=list(map(lambda v:v.group(),(list(map(srch.search,cols)))))
data.columns=new_cols

2
Il est recommandé sur Stack Overflow d'ajouter une explication sur la raison pour laquelle votre solution devrait fonctionner ou est meilleure que les solutions existantes. Pour plus d'informations, consultez Comment répondre .
Samuel Liew

Remarquez comment la réponse la mieux notée nécessite une certaine forme de codage en dur et la réponse la moins bien notée ne nécessite qu'une approche descriptive et procédurale?
Kaustubh J

Il existe de meilleures solutions (plus lisibles) qui utilisent également l'expression régulière que celle-ci. Cela fait bien plus que ce qu'il devrait pour une simple opération de changement de nom. Il y a aussi le danger que le motif ne corresponde à rien, auquel cas vous n'avez rien fait pour gérer les erreurs.
cs95
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.