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 columnsobjeto existente con uno nuevo dada una lista de nombres de columnas de reemplazo.
df.columns = newdonde newestá la lista de nuevos nombres de columnas es tan simple como parece. El inconveniente de este enfoque es que requiere editar el columnsatributo 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 dfcon 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 keysargumento
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 newlista como los nombres de las columnas. Terminamos repitiendo y765. En cambio, podemos usar el keysargumento de la pd.concatfunció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 dtypepara todas las columnas. De lo contrario, terminará con dtype objecttodas 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 transposey set_index. pd.DataFrame.set_indexnos 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 dtypeversus mixta dtypede 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 lambdaen pd.DataFrame.renameese ciclo a través de cada elemento de new
En esta solución, pasamos una lambda que toma xpero luego la ignora. También toma un ypero 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 xy ypuedo proteger mi yvariable. 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