Najpierw zobacz nazwy: names() i colnames()
Nazwy kolumn są przechowywane w atrybucie, który czytasz jak każdy wektor. Dla ramki danych zwracają go zarówno names(), jak i colnames():
Ta sama odpowiedź. Jedyna prawdziwa różnica: colnames() działa też na macierzach, a names() nie, więc kod ogólnego przeznaczenia używa colnames(). Przy codziennych ramkach danych są wymienne.
Najważniejsza myśl dla wszystkiego, co dalej: zmiana nazwy kolumny to przypisanie do tego wektora. Bazowy R nie ma do tego osobnej funkcji; modyfikujesz names(df) tym samym indeksowaniem, którego używasz przy każdym wektorze.
Zmiana według pozycji (działa, ale jest krucha)
Zaindeksuj wektor nazw według pozycji i przypisz wartość:
Kolumna 2 nazywa się teraz price. To dobre do szybkiej poprawki w konsoli, ale w skrypcie jest pułapką. Pozycje to obietnica dotycząca kolejności kolumn, a kolejność kolumn to najmniej stabilna cecha importowanych danych: gdy wczytywany plik CSV dostanie dodatkową kolumnę, names(df)[2] po cichu zmieni nazwę niewłaściwej. Jeśli skrypt zmienia nazwy według pozycji, zmiana schematu zepsuje go bez żadnego komunikatu o błędzie.
Zmiana według nazwy (solidny idiom bazowego R)
Dopasuj starą nazwę zamiast ufać pozycji:
Najpierw przeczytaj część wewnętrzną: names(sales) == "prc" daje FALSE TRUE FALSE, czyli logiczną maskę na wektorze nazw. Indeksowanie nią wybiera pasujący element, a przypisanie go zastępuje. Jeśli "prc" nie istnieje, nic nie pasuje i nic się nie zmienia (bez błędu, więc sprawdź wynik). Ten idiom przetrwa zmianę kolejności, dodane kolumny i skopiowanie do innych skryptów. Zapamiętaj go: to odpowiedź bazowego R na pytanie „jak zmienić nazwę kolumny”.
Kilka naraz
Zastąp cały wektor, gdy nadajesz nazwy wszystkim kolumnom (częste zaraz po imporcie), albo użyj match(), żeby zmienić nazwy wybranego podzbioru:
match(old, names(df)) zwraca pozycje starych nazw, więc nowe nazwy trafiają dokładnie tam, gdzie były stare: tak samo odporne na kolejność jak idiom dla jednej nazwy. Jeśli jakiejś starej nazwy brakuje, match() zwraca NA, a przypisanie kończy się błędem. To właśnie taki sposób zawodzenia, jakiego chcesz: głośny.
setNames() w potokach
Wszystkie powyższe idiomy modyfikują zmienną w dwóch krokach. setNames(object, names) zwraca kopię ze zmienionymi nazwami w jednym wyrażeniu, a tego właśnie potrzebuje potok:
Przydaje się, gdy funkcja zwraca ramkę bez nazw albo ze złymi nazwami i chcesz to naprawić w miejscu, read_something() |> setNames(c("id", "value")), bez tymczasowej zmiennej.
Sposób z dplyr: rename() i rename_with()
rename() z dplyr przyjmuje pary new = old: nowa nazwa jest pierwsza, i każdy choć raz robi to odwrotnie (kod statyczny; piaskownica uruchamia tylko bazowy R):
library(dplyr)
sales |> rename(price = prc, qty = q)
Stare nazwy, których wywołanie nie dotyczy, zostają bez zmian, a literówka w starej nazwie to twardy błąd, a nie ciche nic. To prawdziwa poprawa w stosunku do idiomu bazowego. Do zmiany nazw według reguły, a nie według par, rename_with() stosuje funkcję do nazw:
sales |> rename_with(toupper) # every column
sales |> rename_with(toupper, starts_with("p")) # just some
Zajrzyj do wprowadzenia do dplyr, żeby zobaczyć, jak te funkcje pasują do rodziny czasowników.
Porządkowanie chaotycznych nagłówków z importu
Prawdziwe nagłówki CSV przychodzą jako "Order ID", "unit.price ($)", "2024 Total", czyli nazwy ze spacjami i symbolami, które wszędzie wymuszają cytowanie odwrotnymi apostrofami. Funkcja make.names() z bazowego R zamienia dowolny wektor tekstowy na poprawne nazwy R:
Poprawne, ale na swój sposób brzydkie (X2024.Total). Dlatego wiele zespołów standardowo używa clean_names() z pakietu janitor, która jednym wywołaniem tworzy schludne nazwy w snake_case (order_id, unit_price, x2024_total): df |> janitor::clean_names(). Jeśli co tydzień importujesz chaotyczne pliki, zwraca się od razu.
Najważniejsze informacje
- Nazwy kolumn to po prostu wektor: odczytujesz je przez
names()/colnames(), a zmieniasz, przypisując do niego. names(df)[2] <- "new"jest kruche;names(df)[names(df) == "old"] <- "new"to idiom do zapamiętania.match()zmienia kilka nazw według nazwy;setNames()zmienia nazwy w miejscu, w potoku.rename(new = old)z dplyr zgłasza błąd przy brakujących nazwach (dobrze), arename_with()zmienia nazwy według reguły.- Przy chaotycznych nagłówkach z importu:
make.names()w bazowym R,janitor::clean_names()dla ładnych wyników.
Dalej: sortowanie, czyli sort() dla wektorów, sztuczka z order() dla ramek danych i arrange().
Najczęściej zadawane pytania
Jak zmienić nazwę kolumny w R?
Solidny idiom z bazowego R to dopasowanie po nazwie: names(df)[names(df) == "old"] <- "new". Znajduje kolumnę o nazwie old, gdziekolwiek jest, i zmienia jej nazwę. W dplyr to rename(df, new = old). Zwróć uwagę na kolejność: najpierw nowa nazwa.
Czym różni się names() od colnames()?
W przypadku ramki danych w praktyce niczym: obie odczytują i ustawiają nazwy kolumn. colnames() działa też na macierzach (gdzie names() nie działa), więc kod, który ma obsługiwać oba przypadki, zwykle używa colnames(). Przy zwykłych ramkach danych używaj tej, która ci pasuje.
Jak zmienić nazwę kolumny według pozycji w R?
Przypisz nową wartość w wektorze nazw na tej pozycji: names(df)[2] <- "price" zmienia nazwę drugiej kolumny. To działa, ale jest kruche: gdy tylko dojdzie nowa kolumna albo CSV zmieni kolejność kolumn, pozycja 2 to już inna kolumna. Lepiej zmieniaj nazwy według nazwy.
Jak zmienić nazwy kilku kolumn naraz w R?
Przypisz cały wektor: names(df) <- c("id", "name", "price") zastępuje po kolei wszystkie nazwy. Żeby zmienić nazwy kilku wybranych kolumn według nazwy, użyj match(): names(df)[match(c("old1", "old2"), names(df))] <- c("new1", "new2"). W dplyr: rename(df, new1 = old1, new2 = old2).