Soluzioni a una linea o pipeline
Mi concentrerò su due cose:
OP afferma chiaramente
Ho i nomi delle colonne modificati memorizzati in un elenco, ma non so come sostituire i nomi delle colonne.
Non voglio risolvere il problema di come sostituire '$'o eliminare il primo carattere da ciascuna intestazione di colonna. OP ha già fatto questo passaggio. Invece voglio concentrarmi sulla sostituzione columnsdell'oggetto esistente con uno nuovo dato un elenco di nomi di colonne di sostituzione.
df.columns = newdove si newtrova l'elenco dei nomi delle nuove colonne è semplice come si arriva. Lo svantaggio di questo approccio è che richiede la modifica dell'attributo del frame di dati esistente columnse non è in linea. Mostrerò alcuni modi per eseguire ciò tramite pipelining senza modificare il dataframe esistente.
Installazione 1
Per concentrarsi sulla necessità di rinominare i nomi delle colonne di sostituzione con un elenco preesistente, creerò un nuovo frame di dati di esempio dfcon nomi di colonna iniziali e nomi di nuove colonne non correlati.
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
Soluzione 1
pd.DataFrame.rename
È già stato detto che se avessi un dizionario che mappasse i vecchi nomi di colonna con i nuovi nomi di colonna, potresti usare 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
Tuttavia, puoi facilmente creare quel dizionario e includerlo nella chiamata a rename. Quanto segue sfrutta il fatto che durante l'iterazione dfripetiamo il nome di ogni colonna.
# 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
Funziona alla grande se i nomi delle colonne originali sono univoci. Ma se non lo sono, allora questo si rompe.
Imposta 2
colonne non univoche
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
Soluzione 2
pd.concat usando l' keysargomento
Innanzitutto, nota cosa succede quando proviamo a utilizzare la soluzione 1:
df.rename(columns=dict(zip(df, new)))
y765 y765 z432
0 1 3 5
1 2 4 6
Non abbiamo mappato l' newelenco come nomi di colonna. Abbiamo finito per ripetere y765. Invece, possiamo usare l' keysargomento della pd.concatfunzione mentre si scorre tra le colonne di df.
pd.concat([c for _, c in df.items()], axis=1, keys=new)
x098 y765 z432
0 1 3 5
1 2 4 6
Soluzione 3
Ricostruisci. Questo dovrebbe essere usato solo se ne hai uno singolo dtypeper tutte le colonne. Altrimenti, finirai con dtype objecttutte le colonne e convertirle indietro richiede più lavoro di dizionario.
singolo dtype
pd.DataFrame(df.values, df.index, new)
x098 y765 z432
0 1 3 5
1 2 4 6
Misto 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
Soluzione 4
Questo è un trucco ingannevole con transposee set_index. pd.DataFrame.set_indexci consente di impostare un indice in linea ma non esiste un corrispondente set_columns. Quindi possiamo trasporre, quindi set_index, e trasporre indietro. Tuttavia, lo stesso singolo dtyperispetto al mistodtype avvertimento della soluzione 3 si applica qui.
singolo dtype
df.T.set_index(np.asarray(new)).T
x098 y765 z432
0 1 3 5
1 2 4 6
Misto 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
Soluzione 5
Usa a lambdain pd.DataFrame.renameche cicla attraverso ogni elemento di new
In questa soluzione, passiamo un lambda che prende xma poi lo ignora. Ci vuole anche un yma non se lo aspetta. Invece, un iteratore viene fornito come valore predefinito e posso quindi utilizzarlo per scorrere uno alla volta senza considerare quale sia il valore di x.
df.rename(columns=lambda x, y=iter(new): next(y))
x098 y765 z432
0 1 3 5
1 2 4 6
E come mi hanno indicato le persone nella chat di sopython , se aggiungo una via *di mezzo xe yposso proteggere la mia yvariabile. Tuttavia, in questo contesto, non credo che debba essere protetto. Vale ancora la pena menzionarlo.
df.rename(columns=lambda x, *, y=iter(new): next(y))
x098 y765 z432
0 1 3 5
1 2 4 6