Soluciones de una línea o tubería
Me enfocaré en dos cosas:
OP establece claramente
Tengo los nombres de columna editados almacenados 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 cambio, quiero centrarme en reemplazar el columns
objeto existente con uno nuevo dada una lista de nombres de columnas de reemplazo.
df.columns = new
donde new
está la lista de nuevos nombres de columnas es tan simple como parece. El inconveniente de este enfoque es que requiere editar el columns
atributo del marco de datos existente y no se hace en línea. Mostraré algunas formas de realizar esto mediante la canalización sin editar el marco de datos existente.
Configuración 1
Para centrarnos en la necesidad de cambiar el nombre de los nombres de las columnas de reemplazo por una lista preexistente, crearé un nuevo marco de datos de muestra df
con nombres de columnas iniciales y nombres de columnas 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 nombres de las columnas antiguas a los nuevos, podría usarlo 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 a rename
. Lo siguiente aprovecha el hecho de que cuando iteramos 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 columna originales son únicos. Pero si no lo son, entonces esto se rompe.
Configurar 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
Solución 2
pd.concat
usando el keys
argumento
Primero, observe 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 mapeamos la new
lista como los nombres de las columnas. Terminamos repitiendo y765
. En cambio, podemos usar el keys
argumento de la pd.concat
función mientras iteramos a 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
Solución 3
Reconstruir. Esto solo debe usarse si tiene un solo dtype
para todas las columnas. De lo contrario, terminará con dtype
object
todas las columnas y convertirlas de nuevo requiere más trabajo de diccionario.
Soltero dtype
pd.DataFrame(df.values, df.index, new)
x098 y765 z432
0 1 3 5
1 2 4 6
Mezclado 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
Solución 4
Este es un truco ingenioso con transpose
y set_index
. pd.DataFrame.set_index
nos permite establecer un índice en línea pero no hay correspondencia correspondiente set_columns
. Entonces podemos transponer, entonces set_index
, y volver a transponer. Sin embargo, la misma advertencia simple dtype
versus mixta dtype
de la solución 3 se aplica aquí.
Soltero dtype
df.T.set_index(np.asarray(new)).T
x098 y765 z432
0 1 3 5
1 2 4 6
Mezclado 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
Solución 5
Use a lambda
en pd.DataFrame.rename
ese ciclo a través de cada elemento de new
En esta solución, pasamos una lambda que toma x
pero luego la ignora. También toma un y
pero no lo espera. En cambio, se proporciona 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 señaló la gente en el chat de sopython , si agrego un *
intermedio x
y y
puedo proteger mi y
variable. Sin embargo, en este contexto, no creo que necesite protección. Todavía vale la pena mencionarlo.
df.rename(columns=lambda x, *, y=iter(new): next(y))
x098 y765 z432
0 1 3 5
1 2 4 6