Renommer les colonnes dans les pandas
j'ai une base de données utilisant des pandas et des étiquettes de colonne que je dois éditer pour remplacer les étiquettes de colonne originales.
j'aimerais changer les noms de colonne dans une DataFrame A
où les noms de colonne originaux sont:
['$a', '$b', '$c', '$d', '$e']
à
['a', 'b', 'c', 'd', 'e'].
j'ai les noms de colonne édités stockés dans une liste, mais je ne sais pas comment remplacer les noms de colonne.
28 réponses
il suffit de l'attribuer à l'attribut .columns
:
>>> df = pd.DataFrame({'$a':[1,2], '$b': [10,20]})
>>> df.columns = ['a', 'b']
>>> df
a b
0 1 10
1 2 20
utilisez la fonction df.rename()
et référez les colonnes à renommer. Toutes les colonnes n'ont 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)
la méthode rename
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)
comme indiqué dans http://pandas.pydata.org/pandas-docs/stable/text.html :
df.columns = df.columns.str.replace('$','')
puisque vous voulez seulement supprimer le signe $ dans tous les noms de colonne, vous pouvez juste faire:
df = df.rename(columns=lambda x: x.replace('$', ''))
ou
df.rename(columns=lambda x: x.replace('$', ''), inplace=True)
Pandas De 0,21+ Répondre
il y a eu quelques mises à jour importantes à la colonne Renommer dans la version 0.21.
- la
rename
méthode a ajouté le paramètreaxis
qui peut être réglé surcolumns
ou1
. Cette mise à jour rend cette méthode compatible avec le reste de l'API pandas. Il a toujours les paramètresindex
etcolumns
mais vous n'êtes plus forcé d'utiliser ils. - la
set_axis
méthode avec lainplace
définie àFalse
vous permet de renommer toutes les étiquettes d'index ou de colonne avec une liste.
exemples pour Pandas 0.21+
construire une base de données d'échantillon:
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
utilisant rename
avec axis='columns'
ou axis=1
1519510920"
df.rename({'$a':'a', '$b':'b', '$c':'c', '$d':'d', '$e':'e'}, axis='columns')
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 résultats sont les suivants:
a b c d e
0 1 3 5 7 9
1 2 4 6 8 10
il est encore possible d'utiliser l'ancienne méthode signature:
df.rename(columns={'$a':'a', '$b':'b', '$c':'c', '$d':'d', '$e':'e'})
la fonction rename
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)
utilisant set_axis
avec une liste et inplace=False
You peut fournir une liste à la méthode set_axis
qui est égale en longueur au nombre de colonnes (ou index). Actuellement, inplace
par défaut True
, mais inplace
sera par défaut False
dans les futures versions.
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 à assigner des colonnes directement comme ceci. Il est parfaitement la bonne solution.
l'avantage d'utiliser set_axis
est qu'il peut être utilisé comme partie d'une chaîne de méthode et qu'il renvoie une nouvelle copie de la DataFrame. Sans elle, vous auriez à stocker vos étapes intermédiaires de la chaîne à une autre variable avant de réassigner 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()
df.columns = ['a', 'b', 'c', 'd', 'e']
Il remplacera l'actuel noms avec les noms que vous fournissez, dans l'ordre que vous fournissez.
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)
ainsi vous pouvez éditer manuellement le new_names
comme vous le souhaitez.
Fonctionne très bien lorsque vous avez besoin de renommer seulement quelques colonnes pour corriger des fautes d'orthographe, accents, supprimer des caractères spéciaux, etc.
je pense que cette méthode est utile:
df.rename(columns={"old_column_name1":"new_column_name1", "old_column_name2":"new_column_name2"})
cette méthode vous permet de changer le nom des colonnes individuellement.
noms de colonne vs noms de série
je voudrais expliquer un peu ce qui se passe derrière les coulisses.
Dataframes sont un ensemble de séries.
série à son tour sont une extension d'un numpy.array
numpy.array
s ont un bien .name
C'est le nom de la série. Il est rare que pandas respecte cet attribut, mais il persiste dans les endroits et peut être utilisé pour pirater certains pandas comportements.
nommant la liste des colonnes
beaucoup de réponses ici, parle de "la 151970920" attribut list
alors qu'en fait c'est un Series
. Cela signifie qu'il possède un attribut .name
.
c'est Ce qui arrive si vous décidez de remplir 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 un colonne inférieure.
artéfacts that linger
l'attribut .name
persiste parfois. Si vous mettez df.columns = ['one', 'two']
, alors df.one.name
sera 'one'
.
si vous mettez df.one.name = 'three'
alors df.columns
vous donnera encore ['one', 'two']
, et df.one.name
vous donnera 'three'
mais
pd.DataFrame(df.one)
sera de retour
three
0 1
1 2
2 3
parce que pandas réutilise le .name
du déjà défini Series
.
noms de colonnes à niveaux multiples
Pandas a des façons de faire des noms de colonnes multicouches. Il n'y a pas tellement de magie en jeu mais je voulais couvrir cela dans ma réponse aussi puisque je ne vois personne ramasser sur ce ici.
|one |
|one |two |
0 | 4 | 1 |
1 | 5 | 2 |
2 | 6 | 3 |
cela est facilement réalisable en mettant des colonnes aux listes, comme ceci:
df.columns = [['one', 'one'], ['one', 'two']]
Une ligne ou d'un Pipeline solutions
je vais me concentrer sur deux choses:
-
OP stipule clairement
j'ai les noms de colonne édités stockés dans une liste, mais je ne sais pas comment remplacer les noms de colonne.
Je ne veux pas résoudre le problème de savoir comment remplacer
'$'
ou rayer 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'objet existantcolumns
par un nouvel objet donné une liste de noms de colonne de remplacement. -
df.columns = new
oùnew
est la liste des nouveaux noms de colonnes est aussi simple qu'il obtient. L'inconvénient de cette approche est qu'elle nécessite la modification de l'existant dataframecolumns
attribut et il n'est pas fait en ligne. Je vais vous montrer quelques façons d'effectuer ce via un pipeline sans modification de l'existant dataframe.
Setup 1
Pour mettre l'accent sur la nécessité de renommer les noms de colonnes par une liste préexistante, je vais créer un nouveau datagramme df
avec les noms de colonnes initiales et les noms de nouvelles colonnes sans rapport.
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 faisant correspondre les noms des anciennes colonnes aux nouveaux noms de colonnes, 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 le dictionnaire et l'inclure dans l'appel à rename
. Le suivant prend avantage du fait que lors de l'itération sur 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 colonne originaux sont uniques. Mais si ils ne le sont pas, ce qu'il se décompose.
le programme d'Installation 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
pd.concat
en utilisant l'argument keys
1519560920"
tout d'abord, noter 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 cartographié la liste new
comme noms de colonnes. Nous avons fini par répéter y765
. Au lieu de cela, nous pouvons utiliser l'argument keys
de la fonction pd.concat
tout en itérant à travers 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. Ceci ne doit être utilisé que si vous avez un seul dtype
pour toutes les colonnes. Sinon, vous finirez avec dtype
object
pour toutes les colonnes et leur conversion en arrière nécessite plus de travail de dictionnaire.
Unique 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
C'est une astuce avec transpose
et set_index
. pd.DataFrame.set_index
permet de définir un index en ligne mais il n'y a pas de set_columns
correspondant . Donc nous pouvons transposer, puis set_index
, et transposer en arrière. Cependant, le même single dtype
versus mixte dtype
la mise en garde de la solution 3 s'applique ici.
Unique 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 lambda
dans pd.DataFrame.rename
qui traverse chaque élément de new
Dans ce solution, nous passons une lambda qui prend x
mais l'ignore ensuite. Il faut aussi un y
mais 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 cycle à la fois sans égard à ce que la valeur de x
est.
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 sopython chat, si j'ajoute un *
entre x
et y
, je peux protégez ma variable y
. Bien que, dans ce contexte, Je ne pense pas qu'il ait besoin de protection. Il est toujours intéressant de mentionner.
df.rename(columns=lambda x, *, y=iter(new): next(y))
x098 y765 z432
0 1 3 5
1 2 4 6
DataFrame -- DF.rename () fonctionnera.
df.rename(columns = {'Old Name':'New Name'})
DF est la base de données que vous avez, et le ancien nom est le nom de la colonne vous souhaitez modifier, puis de la Nouveau Nom est le nouveau nom que vous changer. Cette méthode intégrée de DataFrame rend les choses plus faciles.
df = pd.DataFrame({'$a': [1], '$b': [1], '$c': [1], '$d': [1], '$e': [1]})
Si votre nouvelle liste de colonnes dans le même ordre que les colonnes existantes, la mission 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 sur les noms d'anciennes colonnes pour les nouveaux noms de colonnes, vous pourriez faire ce qui suit:
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 dictionnaire cartographique, vous pouvez enlever le symbole $
par une liste de compréhension:
df.columns = [col[1:] if col[0] == '$' else col for col in df]
si vous avez le dataframe, df.les colonnes balancent tout dans une liste que vous pouvez manipuler et ensuite réassigner dans votre dataframe comme les noms des 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
la meilleure façon? IDK. - Oui.
une meilleure façon d'évaluer toutes les principales techniques mises de l'avant dans les réponses à la question Est d'utiliser ci-dessous cProfile pour gage mémoire et temps d'exécution. @ kadee, @kaitlyn, & @eumiro avait les fonctions avec les délais d'exécution les plus rapides - bien que ces fonctions soient si rapides que nous comparons l'Arrondissement 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)')
df = df.rename(columns=lambda n: n.replace('$', ''))
est une façon fonctionnelle de résoudre ce
une autre façon de remplacer les étiquettes originales des colonnes est de retirer les caractères indésirables (ici '$') des étiquettes originales des colonnes.
cela aurait pu être fait en exécutant une boucle for sur df.colonnes et ajout des colonnes dépouillées à df.colonne.
au lieu de cela , nous pouvons le faire proprement dans un seul énoncé en utilisant la compréhension de liste comme ci-dessous:
df.columns = [col.strip('$') for col in df.columns]
( strip
méthode en bandes Python le personnage de début et de la fin de la chaîne.)
je sais que cette question et cette réponse ont été mâchées à mort. Mais j'y ai fait référence pour m'inspirer d'un de mes problèmes . J'ai été capable de le résoudre en utilisant des bits et des morceaux de différentes réponses donc fournir ma réponse au cas où quelqu'un en a besoin.
ma méthode est générique dans laquelle vous pouvez ajouter des délimiteurs supplémentaires par virgule séparant la variable delimiters=
et la future-proof it.
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 ]
sortie:
>>> 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
Real simple il suffit d'utiliser
df.columns = ['Name1', 'Name2', 'Name3'...]
et il assignera les noms de colonne par l'ordre que vous les mettez
vous pouvez utiliser str.slice
pour cela:
df.columns = df.columns.str.slice(1)
df.rename(index=str,columns={'A':'a','B':'b'})
https://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.rename.html
noter que cette approche ne fonctionne pas pour un MultiIndex. Pour un MultiIndex, vous devez faire quelque chose comme ce qui suit:
>>> 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
les colonnes renommer dataframe et remplacer le format
import pandas as pd
data = {'year':[2015,2011,2007,2003,1999,1996,1992,1987,1983,1979,1975],
'team':['Australia','India','Australia','Australia','Australia','Sri Lanka','Pakistan','Australia','India','West Indies','West Indies'],
}
df = pd.DataFrame(data)
#Rename Columns
df.rename(columns={'year':'Years of Win','team':'Winning Team'}, inplace=True)
#Replace format
df = df.columns.str.replace(' ', '_')
si vous avez à traiter avec des charges de colonnes nommées par le système de fourniture hors de votre contrôle, j'ai proposé l'approche suivante qui est une combinaison d'une approche générale et des remplacements spécifiques en une seule fois.
je crée d'abord un dictionnaire à partir des noms de colonnes de dataframe en utilisant des expressions regex afin de jeter certains appendices des noms de colonnes et puis j'ajoute des remplacements spécifiques au dictionnaire pour nommer les colonnes de base comme prévu plus tard dans le base de données de réception.
ceci est ensuite appliqué à la base 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)
une autre option est de renommer en utilisant 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
essayez ceci. Il travaille pour moi
df.rename(index=str, columns={"$a": "a", "$b": "b", "$c" : "c", "$d" : "d", "$e" : "e"})
dans le cas où vous ne voulez pas les noms de ligne df.columns = ['a', 'b',index=False]
Voici une chouette petite fonction que j'aime utiliser pour réduire tapant:
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 comment cela fonctionne:
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')
Renaming columns while reading the Dataframe:
>>> df = pd.DataFrame({'$a': [1], '$b': [1], '$c': [1]}).rename(columns =
{'$a' : 'a','$b':'b','$c':'c'})
Out[1]:
a b c
0 1 1 1