Rozwiązania z jedną linią lub rurociągiem
Skupię się na dwóch rzeczach:
OP jasno stwierdza
Mam edytowane nazwy kolumn zapisane na liście, ale nie wiem, jak zastąpić nazwy kolumn.
Nie chcę rozwiązać problemu zastąpienia '$'
lub usunięcia pierwszego znaku z nagłówka każdej kolumny. OP już zrobił ten krok. Zamiast tego chcę skupić się na zamianie istniejącego columns
obiektu na nowy, biorąc pod uwagę listę nazw kolumn zastępczych.
df.columns = new
gdzie new
lista nazw nowych kolumn jest tak prosta, jak to tylko możliwe. Wadą tego podejścia jest to, że wymaga edycji columns
atrybutu istniejącej ramki danych i nie jest wykonywany bezpośrednio. Pokażę kilka sposobów wykonania tego za pomocą potokowania bez edytowania istniejącej ramki danych.
Konfiguracja 1
Aby skupić się na potrzebie zmiany nazwy zamiany nazw kolumn na wcześniej istniejącą listę, utworzę nową przykładową ramkę danych df
z początkowymi nazwami kolumn i niepowiązanymi nowymi nazwami kolumn.
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
Rozwiązanie 1
pd.DataFrame.rename
Mówiono już, że jeśli masz słownik odwzorowujący stare nazwy kolumn na nowe nazwy kolumn, możesz użyć 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
Możesz jednak łatwo utworzyć ten słownik i dołączyć go do wywołania rename
. Poniższe wykorzystuje fakt, że podczas iteracji df
iterujemy nazwę każdej kolumny.
# 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
Działa to świetnie, jeśli oryginalne nazwy kolumn są unikalne. Ale jeśli nie są, to się psuje.
Skonfiguruj 2
nieunikalne kolumny
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
Rozwiązanie 2
pd.concat
za pomocą keys
argumentu
Najpierw zauważ, co się dzieje, gdy próbujemy użyć rozwiązania 1:
df.rename(columns=dict(zip(df, new)))
y765 y765 z432
0 1 3 5
1 2 4 6
Nie odwzorowaliśmy new
listy jako nazw kolumn. Skończyło się to na powtarzaniu y765
. Zamiast tego możemy użyć keys
argumentu pd.concat
funkcji podczas iteracji po kolumnach df
.
pd.concat([c for _, c in df.items()], axis=1, keys=new)
x098 y765 z432
0 1 3 5
1 2 4 6
Rozwiązanie 3
Zrekonstruuj. Tego należy użyć tylko, jeśli masz jeden dtype
dla wszystkich kolumn. W przeciwnym razie skończysz dtype
object
na wszystkich kolumnach, a ich konwersja z powrotem wymaga większej pracy słownika.
Pojedynczy dtype
pd.DataFrame(df.values, df.index, new)
x098 y765 z432
0 1 3 5
1 2 4 6
Mieszany 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
Rozwiązanie 4
To sztuczka z transpose
i set_index
. pd.DataFrame.set_index
pozwala nam ustawić wbudowany indeks, ale nie ma odpowiadającego set_columns
. Możemy więc przetransponować set_index
i przetransponować z powrotem. Jednak tutaj obowiązuje ten sam zastrzeżenie pojedynczego dtype
kontra mieszanego dtype
z rozwiązania 3.
Pojedynczy dtype
df.T.set_index(np.asarray(new)).T
x098 y765 z432
0 1 3 5
1 2 4 6
Mieszany 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
Roztwór 5
Przy użyciu lambda
w pd.DataFrame.rename
tym, że przełącza się pomiędzy każdym elementem new
W tym rozwiązaniu, przechodzimy lambda, które ma x
ale ignorowany. To także zajmuje, y
ale się tego nie spodziewa. Zamiast tego iterator jest podawany jako wartość domyślna, a następnie mogę go używać do przełączania pojedynczo, bez względu na wartość x
.
df.rename(columns=lambda x, y=iter(new): next(y))
x098 y765 z432
0 1 3 5
1 2 4 6
I jak wskazali mi ludzie na czacie sopython , jeśli dodam *
między nimi x
i y
, mogę chronić moją y
zmienną. Chociaż w tym kontekście nie uważam, że wymaga ochrony. Nadal warto o tym wspomnieć.
df.rename(columns=lambda x, *, y=iter(new): next(y))
x098 y765 z432
0 1 3 5
1 2 4 6