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 columnsobiektu na nowy, biorąc pod uwagę listę nazw kolumn zastępczych.
df.columns = newgdzie newlista nazw nowych kolumn jest tak prosta, jak to tylko możliwe. Wadą tego podejścia jest to, że wymaga edycji columnsatrybutu 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 dfz 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 dfiterujemy 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ą keysargumentu
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 newlisty jako nazw kolumn. Skończyło się to na powtarzaniu y765. Zamiast tego możemy użyć keysargumentu pd.concatfunkcji 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 dtypedla wszystkich kolumn. W przeciwnym razie skończysz dtype objectna 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 transposei set_index. pd.DataFrame.set_indexpozwala nam ustawić wbudowany indeks, ale nie ma odpowiadającego set_columns. Możemy więc przetransponować set_indexi przetransponować z powrotem. Jednak tutaj obowiązuje ten sam zastrzeżenie pojedynczego dtypekontra mieszanego dtypez 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 lambdaw pd.DataFrame.renametym, że przełącza się pomiędzy każdym elementem new
W tym rozwiązaniu, przechodzimy lambda, które ma xale ignorowany. To także zajmuje, yale 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 xi y, mogę chronić moją yzmienną. 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