Ktoś powinien był już o to zapytać, ale nie mogłem znaleźć odpowiedzi. Powiedz, że mam:
x = data.frame(q=1,w=2,e=3, ...and many many columns...)
jaki jest najbardziej elegancki sposób zmiany nazwy dowolnego podzbioru kolumn, których pozycji niekoniecznie znam, na inne dowolne nazwy?
np. powiedz, że chcę zmienić nazwę "q"
i "e"
na "A"
i "B"
jaki jest najbardziej elegancki kod do tego?
Oczywiście mogę zrobić pętlę:
oldnames = c("q","e")
newnames = c("A","B")
for(i in 1:2) names(x)[names(x) == oldnames[i]] = newnames[i]
Ale zastanawiam się, czy istnieje lepszy sposób? Może korzystając z niektórych pakietów? ( plyr::rename
itp.)
old = c("a", "d", "e")
rename_at()
działała przy zmianie nazw zmiennych podzbioru.Z dplyrem zrobiłbyś:
library(dplyr) df = data.frame(q = 1, w = 2, e = 3) df %>% rename(A = q, B = e) # A w B #1 1 2 3
Lub jeśli chcesz użyć wektorów, zgodnie z sugestią @ Jelena-bioinf:
library(dplyr) df = data.frame(q = 1, w = 2, e = 3) oldnames = c("q","e") newnames = c("A","B") df %>% rename_at(vars(oldnames), ~ newnames) # A w B #1 1 2 3
LD Nicolas May zasugerował, że podana zmiana
rename_at
jest zastępowana przezrename_with
:df %>% rename_with(~ newnames[which(oldnames == .x)], .cols = oldnames) # A w B #1 1 2 3
źródło
old
inew
nazwy jako wektory, myślę, żerename_with
może użyć funkcji lub formuły, aby zmienić nazwy wszystkich kolumn podanych jako.cols
argument. Na przykładrename_with(iris, toupper, starts_with("Petal"))
jest równoważnerename_with(iris, ~ toupper(.x), starts_with("Petal"))
.Innym rozwiązaniem dla ramek danych, które nie są zbyt duże, jest (na podstawie odpowiedzi @thelatemail):
x <- data.frame(q=1,w=2,e=3) > x q w e 1 1 2 3 colnames(x) <- c("A","w","B") > x A w B 1 1 2 3
Alternatywnie możesz również użyć:
names(x) <- c("C","w","D") > x C w D 1 1 2 3
Ponadto możesz również zmienić nazwę podzbioru nazw kolumn:
names(x)[2:3] <- c("E","F") > x C E F 1 1 2 3
źródło
Oto najbardziej efektywny sposób, jaki znalazłem, aby zmienić nazwę wielu kolumn za pomocą kombinacji
purrr::set_names()
i kilkustringr
operacji.library(tidyverse) # Make a tibble with bad names data <- tibble( `Bad NameS 1` = letters[1:10], `bAd NameS 2` = rnorm(10) ) data # A tibble: 10 x 2 `Bad NameS 1` `bAd NameS 2` <chr> <dbl> 1 a -0.840 2 b -1.56 3 c -0.625 4 d 0.506 5 e -1.52 6 f -0.212 7 g -1.50 8 h -1.53 9 i 0.420 10 j 0.957 # Use purrr::set_names() with annonymous function of stringr operations data %>% set_names(~ str_to_lower(.) %>% str_replace_all(" ", "_") %>% str_replace_all("bad", "good")) # A tibble: 10 x 2 good_names_1 good_names_2 <chr> <dbl> 1 a -0.840 2 b -1.56 3 c -0.625 4 d 0.506 5 e -1.52 6 f -0.212 7 g -1.50 8 h -1.53 9 i 0.420 10 j 0.957
źródło
~
i.
wset_names()
potoku.purrr::set_names()
.purrr
funkcji tylda~
oznacza „dla każdej kolumny”..
Jest dplyr składni LHS = lewej stronie rury, to znaczy w odniesieniu do przedmiotu, który jest wyprowadzony w tym przypadkudata
.~
to formuła. Możesz również użyć wywołania funkcji i przekazać argumenty do...
argumentuset_names
na przykładrlang::set_names(head(iris), paste0, "_hi")
jest równoważnerlang::set_names(head(iris), ~ paste0(.x, "_hi"))
.Niedawno natknąłem się na to sam, jeśli nie jesteś pewien, czy kolumny istnieją i chcesz zmienić tylko te, które to robią:
existing <- match(oldNames,names(x)) names(x)[na.omit(existing)] <- newNames[which(!is.na(existing))]
źródło
Opierając się na odpowiedzi @ user3114046:
x <- data.frame(q=1,w=2,e=3) x # q w e #1 1 2 3 names(x)[match(oldnames,names(x))] <- newnames x # A w B #1 1 2 3
Nie będzie to zależne od określonej kolejności kolumn w zestawie
x
danych.źródło
match
to dbają. Najlepsze, co zamierzasz zrobić, to prawdopodobnie odpowiedź @ mnelsetnames
.match
nadal jest to polecenie zorientowane na pozycję. W tym duchu uznałem, że pozycja odpowiedzi @ user3114046 jest również oparta na (nawet myślałem, że%in%
polecenie zajmuje się (lub próbuje)). Oczywiście, przypuszczam, że można argumentować, że wszystkie polecenia są zorientowane na pozycję, kiedy przechodzimy do mechanizmu niskiego poziomu ... ale nie o to mi chodzi ... odpowiedź w tabeli danych jest świetna, ponieważ nie ma wielokrotnego wywoływania funkcjiname
polecenia.Zmieniłoby to wszystkie wystąpienia tych liter we wszystkich nazwach:
names(x) <- gsub("q", "A", gsub("e", "B", names(x) ) )
źródło
gsubfn
odpowiedź. Być może przyjdzie G.Grothendieck. On jest regex-meisterem.names(x)[names(x) %in% c("q","e")]<-c("A","B")
źródło
oldnames
jest posortowane tak, żeoldnames[i]
występuje wcześniejoldnames[j]
dla i <j.Możesz pobrać zestaw nazw, zapisać go jako listę, a następnie wykonać zbiorczą zmianę nazwy ciągu. Dobrym przykładem tego jest sytuacja, gdy dokonujesz przejścia od długiego do szerokiego w zbiorze danych:
names(labWide) Lab1 Lab10 Lab11 Lab12 Lab13 Lab14 Lab15 Lab16 1 35.75366 22.79493 30.32075 34.25637 30.66477 32.04059 24.46663 22.53063 nameVec <- names(labWide) nameVec <- gsub("Lab","LabLat",nameVec) names(labWide) <- nameVec "LabLat1" "LabLat10" "LabLat11" "LabLat12" "LabLat13" "LabLat14""LabLat15" "LabLat16" "
źródło
Uwaga, jeśli chcesz połączyć jeden ciąg ze wszystkimi nazwami kolumn, możesz po prostu użyć tego prostego kodu.
colnames(df) <- paste("renamed_",colnames(df),sep="")
źródło
Jeśli tabela zawiera dwie kolumny o tej samej nazwie, kod wygląda następująco:
źródło
Możesz użyć nazwanego wektora.
Z podstawą R (może być nieco niezgrabna):
x = data.frame(q = 1, w = 2, e = 3) rename_vec <- c(q = "A", e = "B") names(x) <- ifelse(is.na(rename_vec[names(x)]), names(x), rename_vec[names(x)]) x #> A w B #> 1 1 2 3
Lub
dplyr
opcja z!!!
:library(dplyr) rename_vec <- c(A = "q", B = "e") # the names are just the other way round than in the base R way! x %>% rename(!!!rename_vec) #> A w B #> 1 1 2 3
Ten ostatni działa, ponieważ operator „big bang”
!!!
wymusza ocenę listy lub wektora.?`!!`
źródło
!!!oldnames
zwraca,c("A", "B")
ale która logika przekształca to wc("A", "w", "B")
??`!!`
Use `!!!` to add multiple arguments to a function. Its argument should evaluate to a list or vector: args <- list(1:3, na.rm = TRUE) ; quo(mean(!!!args))
. Myślę, że dodam to wyjaśnienie do odpowiedzi. Pozdrawiam za wychowanieWiele odpowiedzi, więc właśnie napisałem funkcję, abyś mógł kopiować / wklejać.
rename <- function(x, old_names, new_names) { stopifnot(length(old_names) == length(new_names)) # pull out the names that are actually in x old_nms <- old_names[old_names %in% names(x)] new_nms <- new_names[old_names %in% names(x)] # call out the column names that don't exist not_nms <- setdiff(old_names, old_nms) if(length(not_nms) > 0) { msg <- paste(paste(not_nms, collapse = ", "), "are not columns in the dataframe, so won't be renamed.") warning(msg) } # rename names(x)[names(x) %in% old_nms] <- new_nms x } x = data.frame(q = 1, w = 2, e = 3) rename(x, c("q", "e"), c("Q", "E")) Q w E 1 1 2 3
źródło
rename(x, c("q", "e"), c("Q", "E"))
nie wydaje się już działać w dplyr rename?Jeśli jeden wiersz danych zawiera nazwy, na które chcesz zmienić wszystkie kolumny, możesz to zrobić
names(data) <- data[row,]
Podano
data
twoją ramkę danych irow
numer wiersza zawierającego nowe wartości.Następnie możesz usunąć wiersz zawierający nazwy za pomocą
źródło
To jest funkcja, której potrzebujesz: Następnie po prostu podaj x w zmianie nazwy (X), a zmieni nazwę wszystkich pojawiających się wartości, a jeśli go tam nie ma, nie wystąpi błąd
rename <-function(x){ oldNames = c("a","b","c") newNames = c("d","e","f") existing <- match(oldNames,names(x)) names(x)[na.omit(existing)] <- newNames[which(!is.na(existing))] return(x) }
źródło
Istnieje kilka odpowiedzi dotyczących funkcji
dplyr::rename_with
irlang::set_names
już. Są oddzielne. ta odpowiedź ilustruje różnice między nimi oraz użycie funkcji i formuł do zmiany nazw kolumn.rename_with
zdplyr
pakietu można użyć funkcji lub formuły do zmiany nazwy wybranych kolumn podanych jako.cols
argument. Na przykład przekazanie nazwy funkcjitoupper
:library(dplyr) rename_with(head(iris), toupper, starts_with("Petal"))
Jest równoznaczne z przekazaniem wzoru
~ toupper(.x)
:rename_with(head(iris), ~ toupper(.x), starts_with("Petal"))
Zmieniając nazwy wszystkich kolumn, możesz także użyć
set_names
z pakietu rlang. Aby zrobić inny przykład, użyjmypaste0
jako funkcji zmiany nazwy.pasteO
przyjmuje 2 argumenty, w rezultacie istnieją różne sposoby przekazania drugiego argumentu w zależności od tego, czy używamy funkcji, czy formuły.rlang::set_names(head(iris), paste0, "_hi") rlang::set_names(head(iris), ~ paste0(.x, "_hi"))
To samo można osiągnąć
rename_with
, przekazując ramkę danych jako pierwszy argument.data
, funkcję jako drugi argument.fn
, wszystkie kolumny jako trzeci argument.cols=everything()
i parametry funkcji jako czwarty argument...
. Alternatywnie możesz umieścić drugi, trzeci i czwarty argument we wzorze podanym jako drugi argument.rename_with(head(iris), paste0, everything(), "_hi") rename_with(head(iris), ~ paste0(.x, "_hi"))
rename_with
działa tylko z ramkami danych.set_names
jest bardziej ogólny i może również zmieniać nazwy wektorówrlang::set_names(1:4, c("a", "b", "c", "d"))
źródło