Tengo un DataFrame con pandas y etiquetas de columna que necesito editar para reemplazar las etiquetas de columna originales.

Me gustaría cambiar los nombres de columna en un DataFrame A donde están los nombres de columna originales:

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

Para

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

Tengo los nombres de columna editados almacenados en una lista, pero no sé cómo reemplazar los nombres de columna.

2075
user1504276 5 jul. 2012 a las 18:21

21 respuesta

La mejor respuesta

Simplemente asígnelo al atributo .columns:

>>> df = pd.DataFrame({'$a':[1,2], '$b': [10,20]})
>>> df.columns = ['a', 'b']
>>> df
   a   b
0  1  10
1  2  20
1718
eumiro 5 jul. 2012 a las 14:23

Otra opción es renombrar usando una expresión regular:

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
8
sbha 7 jul. 2018 a las 02:07

Asumiendo que puedes usar expresiones regulares. Esta solución elimina la necesidad de codificación manual usando regex

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
Kaustubh J 12 abr. 2019 a las 03:34
df.rename(index=str,columns={'A':'a','B':'b'})

https://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.rename.html

15
Yog 29 ago. 2018 a las 13:35

Pandas 0.21+ Respuesta

Ha habido algunas actualizaciones significativas para cambiar el nombre de la columna en la versión 0.21.

  • El {{ X0}} método ha agregado el parámetro axis que se puede establecer en columns o 1. Esta actualización hace que este método coincida con el resto de la API de pandas. Todavía tiene los parámetros index y columns pero ya no estás obligado a usarlos.
  • El {{X0} } método con inplace establecido en False le permite cambiar el nombre de todas las etiquetas de índice o columna con una lista.

Ejemplos para Pandas 0.21+

Construya el DataFrame de muestra:

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

Usando rename con axis='columns' o axis=1

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

O

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

Ambos resultan en lo siguiente:

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

Todavía es posible usar la firma del método anterior:

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

La función rename también acepta funciones que se aplicarán a cada nombre de columna.

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

O

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

Usando set_axis con una lista y inplace=False

Puede proporcionar una lista al método set_axis que tenga la misma longitud que el número de columnas (o índice). Actualmente, inplace tiene como valor predeterminado True, pero inplace tendrá como valor predeterminado False en futuras versiones.

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

O

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

¿Por qué no usar df.columns = ['a', 'b', 'c', 'd', 'e']?

No hay nada de malo en asignar columnas directamente como esta. Es una solución perfectamente buena.

La ventaja de usar set_axis es que puede usarse como parte de una cadena de métodos y que devuelve una nueva copia del DataFrame. Sin él, tendría que almacenar sus pasos intermedios de la cadena en otra variable antes de reasignar las columnas.

# 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()
162
JohnE 17 nov. 2017 a las 19:31

Si tiene el marco de datos, df.columns volca todo en una lista que puede manipular y luego reasignar a su marco de datos como los nombres de las columnas ...

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

¿Mejor manera? NO SÉ. Un camino, sí.

A continuación se muestra una mejor manera de evaluar todas las técnicas principales presentadas en las respuestas a la pregunta utilizando cProfile para medir la memoria y el tiempo de ejecución. @kadee, @kaitlyn y @eumiro tenían las funciones con los tiempos de ejecución más rápidos, aunque estas funciones son tan rápidas que estamos comparando el redondeo de .000 y .001 segundos para todas las respuestas. Moraleja: mi respuesta anterior probablemente no sea la mejor manera.

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)')
17
andrewwowens 7 sep. 2016 a las 02:24
df = pd.DataFrame({'$a': [1], '$b': [1], '$c': [1], '$d': [1], '$e': [1]})

Si su nueva lista de columnas está en el mismo orden que las columnas existentes, la asignación es 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 tenía un diccionario tecleado en los nombres de columnas antiguas a nombres de columnas nuevas, podría hacer lo siguiente:

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 no tiene una lista o una asignación de diccionario, puede quitar el símbolo $ inicial a través de una comprensión de la lista:

df.columns = [col[1:] if col[0] == '$' else col for col in df]
17
Alexander 13 sep. 2017 a las 12:24

Sé que esta pregunta y respuesta han sido masticadas hasta la muerte. Pero me referí a él como inspiración para uno de los problemas que estaba teniendo. Pude resolverlo usando fragmentos de diferentes respuestas, por lo tanto, proporcioné mi respuesta en caso de que alguien la necesite.

Mi método es genérico en el que puede agregar delimitadores adicionales separando por coma la variable delimiters= y preparándolo para el futuro.

Código de trabajo:

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 ]

Salida:

>>> 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
9
Anil_M 4 ago. 2016 a las 20:26

Puede usar str.slice para eso:

df.columns = df.columns.str.slice(1)
10
Anton Protopopov 28 ene. 2016 a las 17:31

El rename puede tomar una función , por ejemplo:

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)
383
smci 20 oct. 2019 a las 22:06
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 esta manera, puede editar manualmente el new_names como lo desee. Funciona muy bien cuando necesita cambiar el nombre de unas pocas columnas para corregir errores ortográficos, acentos, eliminar caracteres especiales, etc.

59
migloo 21 may. 2015 a las 17:54

Si tiene que lidiar con un montón de columnas nombradas por el sistema proveedor fuera de su control, se me ocurrió el siguiente enfoque que es una combinación de un enfoque general y reemplazos específicos de una sola vez.

Primero cree un diccionario a partir de los nombres de columna del marco de datos utilizando expresiones de expresiones regulares para descartar ciertos apéndices de nombres de columna y luego agregue reemplazos específicos al diccionario para nombrar columnas centrales como se espera más adelante en la base de datos receptora.

Esto se aplica al marco de datos de una vez.

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)
6
Chris A 5 jul. 2019 a las 11:46

RENOMBRAR COLUMNAS ESPECÍFICAS

Utilice la función df.rename() y referir las columnas a renombrar. No todas las columnas deben ser renombradas:

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)

Ejemplo de código mínimo

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

Los siguientes métodos funcionan y producen el mismo resultado:

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

Recuerde asignar el resultado nuevamente, ya que la modificación no está en su lugar. Alternativamente, especifique 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

Desde v0.25, también puede especificar errors='raise' para generar errores si se especifica una columna para cambiar el nombre no válida. Consulte v0. 25 rename() documentos.


REASIGNAR CABEZALES DE COLUMNA

Utilice df.set_axis() con axis=1 y inplace=False (para devolver una copia).

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

Utilicé el inplace=True de Quartz hook y bucle de eventos, y el marco de Cocoa AppKit para descifrar códigos clave para lograr esto.…

También puede asignar encabezados directamente:

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
2669
cs95 29 may. 2019 a las 19:50

Aquí hay una pequeña función ingeniosa que me gusta usar para reducir la escritura:

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   

Aquí hay un ejemplo de cómo funciona:

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')
4
seeiespi 18 may. 2018 a las 23:36

Tenga en cuenta que este enfoque no funciona para un MultiIndex. Para un MultiIndex, debe hacer algo como lo siguiente:

>>> 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
oxer 29 ago. 2016 a las 21:27

Otra forma en que podríamos reemplazar las etiquetas de columna originales es quitando los caracteres no deseados (aquí '$') de las etiquetas de columna originales.

Esto podría haberse hecho ejecutando un bucle for sobre df.columns y agregando las columnas despojadas a df.columns.

En cambio, podemos hacer esto ordenadamente en una sola declaración usando la comprensión de la lista como a continuación:

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

(El método strip en Python elimina el carácter dado desde el principio y el final de la cadena).

13
piet.t 5 jul. 2017 a las 13:19

Nombres de columna versus nombres de series

Me gustaría explicar un poco lo que sucede detrás de escena.

Los marcos de datos son un conjunto de series.

Las series a su vez son una extensión de un numpy.array

numpy.array s tienen una propiedad .name

Este es el nombre de la serie. Rara vez los pandas respetan este atributo, pero persiste en algunos lugares y puede usarse para piratear algunos comportamientos de los pandas.

Nombrar la lista de columnas

Muchas respuestas aquí hablan de que el atributo df.columns es un list cuando de hecho es un Series. Esto significa que tiene un atributo .name.

Esto es lo que sucede si decide completar el nombre de las columnas 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

Tenga en cuenta que el nombre del índice siempre viene una columna más abajo.

Artefactos que permanecen

El atributo .name persiste a veces. Si configura df.columns = ['one', 'two'], entonces df.one.name será 'one'.

Si configura df.one.name = 'three' entonces df.columns aún le dará ['one', 'two'], y df.one.name le dará 'three'

Pero

pd.DataFrame(df.one) volverá

    three
0       1
1       2
2       3

Porque los pandas reutilizan el .name del Series ya definido.

Nombres de columna de niveles múltiples

Pandas tiene formas de hacer nombres de columnas de varias capas. No hay tanta magia involucrada, pero también quería cubrir esto en mi respuesta, ya que no veo a nadie entendiendo esto aquí.

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

Esto se puede lograr fácilmente configurando columnas en listas, como esta:

df.columns = [['one', 'one'], ['one', 'two']]
33
firelynx 29 sep. 2016 a las 12:30

Realmente simple solo use

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

Y asignará los nombres de columna por el orden en que los colocó

12
Thodoris P 29 nov. 2015 a las 19:22
df.columns = ['a', 'b', 'c', 'd', 'e']

Reemplazará los nombres existentes con los nombres que proporcione, en el orden que proporcione.

75
Mike_K 12 oct. 2018 a las 05:45

Como se documenta en http://pandas.pydata.org/pandas-docs/stable/text.html:

df.columns = df.columns.str.replace('$','')
172
kadee 30 may. 2015 a las 13:24

Como solo desea eliminar el signo $ en todos los nombres de columna, puede hacer lo siguiente:

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

O

df.rename(columns=lambda x: x.replace('$', ''), inplace=True)
130
paulo.filip3 26 mar. 2014 a las 10:20