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 columns
dell'oggetto esistente con uno nuovo dato un elenco di nomi di colonne di sostituzione.
df.columns = new
dove si new
trova 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 columns
e 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 df
con 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 df
ripetiamo 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' keys
argomento
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' new
elenco come nomi di colonna. Abbiamo finito per ripetere y765
. Invece, possiamo usare l' keys
argomento della pd.concat
funzione 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 dtype
per tutte le colonne. Altrimenti, finirai con dtype
object
tutte 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 transpose
e set_index
. pd.DataFrame.set_index
ci 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 dtype
rispetto 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 lambda
in pd.DataFrame.rename
che cicla attraverso ogni elemento di new
In questa soluzione, passiamo un lambda che prende x
ma poi lo ignora. Ci vuole anche un y
ma 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 x
e y
posso proteggere la mia y
variabile. 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