Renombrar columnas específicas en pandas

182

Tengo un marco de datos llamado data. ¿Cómo cambiaría el nombre del único encabezado de columna? Por ejemplo gdpa log(gdp)?

data =
    y  gdp  cap
0   1    2    5
1   2    3    9
2   8    7    2
3   3    4    7
4   6    7    7
5   4    8    3
6   8    2    8
7   9    9   10
8   6    6    4
9  10   10    7
natsuki_2002
fuente
77
Definitivamente hay una superposición, pero en "Renombrar columnas en pandas" no me quedó claro de inmediato que se podría seleccionar un elemento de columna solitario para renombrar. Por supuesto, en retrospectiva es obvio, y si hubiera profundizado más, probablemente lo habría descubierto, pero creo que esta pregunta / respuesta es mejor para señalarlo.
jeremiahbuddha

Respuestas:

360
data.rename(columns={'gdp':'log(gdp)'}, inplace=True)

El renameprograma que acepta un dict como parámetro para columnsque solo pase un dict con una sola entrada.

Ver también relacionados

EdChum
fuente
3
Esto lleva mucho tiempo en un gran marco de datos, ¿así que creo que esto hace algún tipo de copia de todo el marco de datos en la memoria?
elgehelge
1
@elgehelge no debería hacerlo, la mayoría de las operaciones de pandas devolverán una copia y algunos aceptan un inplaceparámetro, si está ignorando este parámetro, entonces es un error, ¿puedes hacer tiempos con y sin el parámetro, también intenta algo como new_df = df.rename(columns={'new_name':'old_name'})y ver si esto es más rápido o no
EdChum
1
@ EdChum Gracias. Eliminar el inplaceparámetro casi duplicó el tiempo de 14 segundos a 26 segundos. Pero 14 segundos todavía son bastante tiempo solo para cambiar el encabezado ...
elgehelge 05 de
2
solo una nota, ¡cuidado! si la columna de destino no existe, (deletreando mal el nombre más o menos), esto no hará nada sin ningún error o advertencia.
Amir
1
@Quastiat es un poco deprimente por qué algunas de estas operaciones simples son más rápidas al hacer una comprensión de la lista. Fundamentalmente, a menos que tenga un df muy grande, entonces no debería importar a menos que
cambie el
27

Una implementación mucho más rápida sería usar list-comprehensionsi necesita cambiar el nombre de una sola columna.

df.columns = ['log(gdp)' if x=='gdp' else x for x in df.columns]

Si surge la necesidad de cambiar el nombre de varias columnas, use expresiones condicionales como:

df.columns = ['log(gdp)' if x=='gdp' else 'cap_mod' if x=='cap' else x for x in df.columns]

O bien, construya una asignación utilizando a dictionaryy realice la operación list-comprehensioncon ella getestableciendo el valor predeterminado como el nombre antiguo:

col_dict = {'gdp': 'log(gdp)', 'cap': 'cap_mod'}   ## key→old name, value→new name

df.columns = [col_dict.get(x, x) for x in df.columns]

Tiempos:

%%timeit
df.rename(columns={'gdp':'log(gdp)'}, inplace=True)
10000 loops, best of 3: 168 µs per loop

%%timeit
df.columns = ['log(gdp)' if x=='gdp' else x for x in df.columns]
10000 loops, best of 3: 58.5 µs per loop
Nickil Maveli
fuente
Me encantaría usar este método, pero desafortunadamente no funciona pd.merge_asof()porque es una expresión :(.
thdoan
14

¿Cómo cambio el nombre de una columna específica en pandas?

Desde v0.24 +, para cambiar el nombre de una (o más) columnas a la vez,

Si necesita cambiar el nombre de TODAS las columnas a la vez,

  • DataFrame.set_axis()método con axis=1. Pase una secuencia similar a una lista. Las opciones también están disponibles para modificaciones en el lugar.

rename con axis=1

df = pd.DataFrame('x', columns=['y', 'gdp', 'cap'], index=range(5))
df

   y gdp cap
0  x   x   x
1  x   x   x
2  x   x   x
3  x   x   x
4  x   x   x

Con 0.21+, ahora puede especificar un axisparámetro con rename:

df.rename({'gdp':'log(gdp)'}, axis=1)
# df.rename({'gdp':'log(gdp)'}, axis='columns')
    
   y log(gdp) cap
0  x        x   x
1  x        x   x
2  x        x   x
3  x        x   x
4  x        x   x

(Tenga en cuenta que renameno está en su lugar de forma predeterminada, por lo que deberá volver a asignar el resultado ).

Esta adición se ha realizado para mejorar la coherencia con el resto de la API. El nuevo axisargumento es análogo al columnsparámetro: hacen lo mismo.

df.rename(columns={'gdp': 'log(gdp)'})

   y log(gdp) cap
0  x        x   x
1  x        x   x
2  x        x   x
3  x        x   x
4  x        x   x

rename también acepta una devolución de llamada que se llama una vez para cada columna.

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

   y  g  c
0  x  x  x
1  x  x  x
2  x  x  x
3  x  x  x
4  x  x  x

Para este escenario específico, desearía utilizar

df.rename(lambda x: 'log(gdp)' if x == 'gdp' else x, axis=1)

Index.str.replace

Similar al replacemétodo de cadenas en python, el índice y la serie pandas (solo tipo de objeto) definen un str.replacemétodo ("vectorizado") para el reemplazo basado en cadenas y expresiones regulares.

df.columns = df.columns.str.replace('gdp', 'log(gdp)')
df
 
   y log(gdp) cap
0  x        x   x
1  x        x   x
2  x        x   x
3  x        x   x
4  x        x   x

La ventaja de esto sobre los otros métodos es que str.replaceadmite expresiones regulares (habilitado por defecto). Vea los documentos para más información.


Pasando una lista a set_axisconaxis=1

Llame set_axiscon una lista de encabezado (s). La lista debe tener la misma longitud que el tamaño de las columnas / índice. set_axismuta el DataFrame original de forma predeterminada, pero puede especificar inplace=Falseque devuelva una copia modificada.

df.set_axis(['cap', 'log(gdp)', 'y'], axis=1, inplace=False)
# df.set_axis(['cap', 'log(gdp)', 'y'], axis='columns', inplace=False)

  cap log(gdp)  y
0   x        x  x
1   x        x  x
2   x        x  x
3   x        x  x
4   x        x  x

Nota: En futuras versiones, el inplacevalor predeterminado será True.

Método de encadenamiento
¿Por qué elegir set_axiscuando ya tenemos una manera eficiente de asignar columnas df.columns = ...? Como lo muestra Ted Petrou en [esta respuesta], ( https://stackoverflow.com/a/46912050/4909087 ) set_axises útil cuando se intentan encadenar métodos.

Comparar

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

Versus

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

La primera es una sintaxis más natural y de flujo libre.

cs95
fuente
3

Hay al menos cinco formas diferentes de cambiar el nombre de columnas específicas en pandas, y las he enumerado a continuación junto con enlaces a las respuestas originales. También cronometré estos métodos y descubrí que funcionan aproximadamente igual (aunque YMMV depende de su conjunto de datos y escenario). El caso de prueba a continuación es para cambiar el nombre de columnas A M N Za A2 M2 N2 Z2en una trama de datos con las columnas Aa Zque contiene un millón de filas.

# Import required modules
import numpy as np
import pandas as pd
import timeit

# Create sample data
df = pd.DataFrame(np.random.randint(0,9999,size=(1000000, 26)), columns=list('ABCDEFGHIJKLMNOPQRSTUVWXYZ'))

# Standard way - https://stackoverflow.com/a/19758398/452587
def method_1():
    df_renamed = df.rename(columns={'A': 'A2', 'M': 'M2', 'N': 'N2', 'Z': 'Z2'})

# Lambda function - https://stackoverflow.com/a/16770353/452587
def method_2():
    df_renamed = df.rename(columns=lambda x: x + '2' if x in ['A', 'M', 'N', 'Z'] else x)

# Mapping function - https://stackoverflow.com/a/19758398/452587
def rename_some(x):
    if x=='A' or x=='M' or x=='N' or x=='Z':
        return x + '2'
    return x
def method_3():
    df_renamed = df.rename(columns=rename_some)

# Dictionary comprehension - https://stackoverflow.com/a/58143182/452587
def method_4():
    df_renamed = df.rename(columns={col: col + '2' for col in df.columns[
        np.asarray([i for i, col in enumerate(df.columns) if 'A' in col or 'M' in col or 'N' in col or 'Z' in col])
    ]})

# Dictionary comprehension - https://stackoverflow.com/a/38101084/452587
def method_5():
    df_renamed = df.rename(columns=dict(zip(df[['A', 'M', 'N', 'Z']], ['A2', 'M2', 'N2', 'Z2'])))

print('Method 1:', timeit.timeit(method_1, number=10))
print('Method 2:', timeit.timeit(method_2, number=10))
print('Method 3:', timeit.timeit(method_3, number=10))
print('Method 4:', timeit.timeit(method_4, number=10))
print('Method 5:', timeit.timeit(method_5, number=10))

Salida:

Method 1: 3.650640267
Method 2: 3.163998427
Method 3: 2.998530871
Method 4: 2.9918436889999995
Method 5: 3.2436501520000007

Use el método que le resulte más intuitivo y más fácil de implementar en su aplicación.

Thdoan
fuente