Renombrando columnas en pandas

Tengo un dataframe que utiliza pandas y tags de columna que necesito editar para reemplazar las tags de columna originales.

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

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

a

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

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

    Solo .columns atributo .columns :

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

    Utilice la función df.rename() y refiera las columnas a las que desea cambiar el nombre. No todas las columnas tienen que 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) 

    El método de 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) 

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

     df.columns = df.columns.str.replace('$','') 

    Pandas 0.21+ Respuesta

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

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

    Ejemplos para Pandas 0.21+

    Construir muestra 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 

    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:

      abcde 0 1 3 5 7 9 1 2 4 6 8 10 

    Todavía es posible utilizar la firma del método antiguo:

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

    La función de 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 e inplace=False

    Puede proporcionar una lista al método set_axis que es igual en longitud al número de columnas (o índice). Actualmente, los inplace predeterminados en el lugar son True , pero los valores predeterminados en el inplace serán 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 de esta manera. Es una solución perfectamente buena.

    La ventaja de usar set_axis es que se puede usar 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 a 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() 

    Ya que solo desea eliminar el signo $ en todos los nombres de columna, simplemente puede hacer:

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

    O

     df.rename(columns=lambda x: x.replace('$', ''), inplace=True) 
     df.columns = ['a', 'b', 'c', 'd', 'e'] 

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

     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 puedes editar manualmente los new_names como desees. Funciona muy bien cuando necesita cambiar el nombre de solo unas pocas columnas para corregir errores de ortografía, acentos, eliminar caracteres especiales, etc.

    Creo que este método es útil:

     df.rename(columns={"old_column_name1":"new_column_name1", "old_column_name2":"new_column_name2"}) 

    Este método le permite cambiar los nombres de columna individualmente.

    Nombres de columnas vs 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 tiene una propiedad .name

    Este es el nombre de la serie. Raras veces los pandas respetan este atributo, pero permanece en algunos lugares y se puede usar para piratear algunos comportamientos de pandas.

    Nombrando la lista de columnas

    Muchas respuestas aquí hablan de que el atributo df.columns es una list cuando en realidad es una 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 aparece una columna más abajo.

    Artefactos que perduran

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

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

    PERO

    pd.DataFrame(df.one) devolverá

      three 0 1 1 2 2 3 

    Porque los pandas reutilizan el .name de la serie ya definida.

    Nombres de columnas multi nivel

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

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

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

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

    Soluciones de una línea o tubería.

    Me centraré en dos cosas:

    1. OP establece claramente

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

      No quiero resolver el problema de cómo reemplazar '$' o quitar el primer carácter de cada encabezado de columna. OP ya ha hecho este paso. En su lugar, quiero centrarme en reemplazar el objeto de columns existente por uno nuevo dada una lista de nombres de columnas de reemplazo.

    2. df.columns = new donde new es la lista de nuevos nombres de columnas es tan simple como se obtiene. El inconveniente de este enfoque es que requiere editar el atributo de columns del dataframe existente y no se realiza en línea. Mostraré algunas formas de realizar esto a través de la canalización sin editar el dataframe existente.


    Configuración 1
    Para centrarme en la necesidad de cambiar el nombre de reemplazar los nombres de columna con una lista preexistente, crearé un nuevo df datos de muestra con nombres de columna iniciales y nombres de columna nuevos no relacionados.

     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 

    Solución 1
    pd.DataFrame.rename

    Ya se ha dicho que si tuviera un diccionario que asignara los antiguos nombres de columna a nuevos nombres de columna, podría usar 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 

    Sin embargo, puede crear fácilmente ese diccionario e incluirlo en la llamada para rename . Lo siguiente se aprovecha del hecho de que al iterar sobre df , iteramos sobre cada nombre de columna.

     # 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 

    Esto funciona muy bien si los nombres de sus columnas originales son únicos. Pero si no lo son, entonces esto se rompe.


    Configuración 2
    columnas no únicas

     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 

    Solucion 2
    pd.concat usando el argumento keys

    Primero, note lo que sucede cuando intentamos usar la solución 1:

     df.rename(columns=dict(zip(df, new))) y765 y765 z432 0 1 3 5 1 2 4 6 

    No asignamos la new lista como los nombres de columna. Terminamos repitiendo y765 . En su lugar, podemos usar el argumento de keys de la función pd.concat mientras pd.concat través de las columnas 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 

    Solucion 3
    Reconstruir. Esto solo debe usarse si tiene un único tipo de dtype para todas las columnas. De lo contrario, terminará con el object dtype para todas las columnas y volver a convertirlas requiere más trabajo de diccionario.

    dtype solo

     pd.DataFrame(df.values, df.index, new) x098 y765 z432 0 1 3 5 1 2 4 6 

    dtype mixto

     pd.DataFrame(df.values, df.index, new).astype(dict(zip(new, df.dtypes))) x098 y765 z432 0 1 3 5 1 2 4 6 

    Solucion 4
    Este es un truco de trucos con transpose y set_index . pd.DataFrame.set_index nos permite establecer un índice en línea pero no hay un conjunto de set_columns correspondientes. Así que podemos transponer, luego set_index , y transponer de vuelta. Sin embargo, aquí se aplica la misma advertencia de tipo de dtype frente a tipo mixto de la solución 3.

    dtype solo

     df.T.set_index(np.asarray(new)).T x098 y765 z432 0 1 3 5 1 2 4 6 

    dtype mixto

     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 

    Solucion 5
    Use una lambda en pd.DataFrame.rename que pd.DataFrame.rename cada elemento de new
    En esta solución, pasamos un lambda que toma x pero luego lo ignora. También toma una y pero no lo espera. En su lugar, se asigna un iterador como valor predeterminado y luego puedo usarlo para recorrer uno a la vez sin tener en cuenta cuál es el valor de x .

     df.rename(columns=lambda x, y=iter(new): next(y)) x098 y765 z432 0 1 3 5 1 2 4 6 

    Y como me lo indicó la gente en el chat de sopython , si agrego un * entre x y y , puedo proteger mi variable y . Aunque, en este contexto, no creo que necesite protección. Todavía vale la pena mencionar.

     df.rename(columns=lambda x, *, y=iter(new): next(y)) x098 y765 z432 0 1 3 5 1 2 4 6 
     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 abcde 0 1 1 1 1 1 

    Si tenía un diccionario codificado en los nombres de columna antiguos a los nombres de columna nuevos, 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 abcde 0 1 1 1 1 1 

    Si no tiene una lista o una asignación de diccionario, puede quitar el símbolo de $ inicial a través de una lista de comprensión:

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

    df = df.rename(columns=lambda n: n.replace('$', '')) es una forma funcional de resolver esto

    Si tienes el dataframe, df.columns vuelca todo en una lista que puedes manipular y luego reasignar a tu dataframe 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? IDK. Una forma – si.

    Una mejor manera de evaluar todas las técnicas principales presentadas en las respuestas a la pregunta es a continuación, usando cProfile para calibrar la memoria y el tiempo de ejecución. @kadee, @kaitlyn y @eumiro tuvieron 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” forma.

     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)') 

    Otra forma en que podríamos reemplazar las tags de columna originales es eliminando los caracteres no deseados (aquí ‘$’) de las tags de columna originales.

    Esto se podría haber hecho ejecutando un bucle for sobre df.columns y agregando las columnas eliminadas a df.columns.

    En su lugar, podemos hacerlo de manera ordenada en una sola statement utilizando la comprensión de lista como se muestra a continuación:

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

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

    Sé que esta pregunta y respuesta ha sido masticada hasta la muerte. Pero me referí a él como inspiración para uno de los problemas que estaba teniendo. Pude resolverlo utilizando bits y piezas de respuestas diferentes, por lo tanto, proporcioné mi respuesta en caso de que alguien la necesitara.

    Mi método es genérico, en el que puede agregar delimitadores adicionales separando los delimiters= con comas delimiters= variable y probarlo 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 abcde 0 1 3 5 7 9 1 2 4 6 8 10 

    Real solo uso simple

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

    y asignará los nombres de las columnas por el orden en que los pones.

    Podrías usar str.slice para eso:

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

    Tenga en cuenta que estos enfoques no funcionan para un MultiIndex. Para un MultiIndex, necesita hacer algo como lo siguiente:

     >>> df = pd.DataFrame({('$a','$x'):[1,2], ('$b','$y'): [3,4], ('e','f'):[5,6]}) >>> df $a $be $x $yf 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 abe xyf 0 1 3 5 1 2 4 6 

    Cambiar el nombre de las columnas del dataframe y reemplazar el formato

     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(' ', '_') 

    Otra opción es cambiar el nombre 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 abc 0 1 3 5 1 2 4 6 

    Renombrando columnas mientras lees el Dataframe:

     >>> df = pd.DataFrame({'$a': [1], '$b': [1], '$c': [1]}).rename(columns = {'$a' : 'a','$b':'b','$c':'c'}) Out[1]: abc 0 1 1 1 

    Importar bibliotecas que nos ayudarán a crear un dataframe:

     import pandas as pd import numpy as np 

    Crear dataframe:

     df = pd.DataFrame(np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]), columns=['a', 'b', 'c']) 

    Cambiar el nombre de Dataframe:

     df.rename(columns={'a':'x', 'b':'y', 'c':'z'}, index=str) 

    df.columns ahora debería tener diferentes valores

    Si tiene que lidiar con un montón de columnas nombradas por el sistema que está 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 creo un diccionario a partir de los nombres de las columnas del dataframe usando expresiones regulares para eliminar ciertos apéndices de los nombres de las columnas y luego agrego reemplazos específicos al diccionario para nombrar las columnas centrales como se espera más adelante en la base de datos de recepción.

    Esto se aplica a la estructura de datos de una sola 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) 

    Veo 3 maneras fáciles

    df.columns

    salida: [‘$ a’, ‘$ b’, ‘$ c’, ‘$ d’, ‘$ e’]

    1.

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

    2.

    df.columns = df.columns.str.replace('$','')

    3.

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

    En caso de que no quiera los nombres de fila df.columns = ['a', 'b',index=False]

    Prueba esto. Esto funciona para mi

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

    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') 
     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.columns = df.columns.str.replace(' ', '_')