Alguien debería haber preguntado esto ya, pero no pude encontrar una respuesta. Di que tengo:
x = data.frame(q=1,w=2,e=3, ...and many many columns...)
¿Cuál es la forma más elegante de cambiar el nombre de un subconjunto arbitrario de columnas, cuya posición no necesariamente conozco, a otros nombres arbitrarios?
Por ejemplo, digamos que quiero cambiar el nombre "q"
y "e"
en "A"
y "B"
, ¿cuál es el código más elegante para hacer esto?
Obviamente, puedo hacer un bucle:
oldnames = c("q","e")
newnames = c("A","B")
for(i in 1:2) names(x)[names(x) == oldnames[i]] = newnames[i]
Pero me pregunto si hay una mejor manera. ¿Quizás usando algunos de los paquetes? ( plyr::rename
etc.)
old = c("a", "d", "e")
rename_at()
funcionó para cambiar los nombres de las variables de un subconjunto.Con dplyr harías:
library(dplyr) df = data.frame(q = 1, w = 2, e = 3) df %>% rename(A = q, B = e) # A w B #1 1 2 3
O si desea usar vectores, como lo sugiere @ 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 sugirió que un cambio dado
rename_at
está siendo reemplazado porrename_with
:df %>% rename_with(~ newnames[which(oldnames == .x)], .cols = oldnames) # A w B #1 1 2 3
fuente
old
ynew
nombres como vectores, creoOtra solución para marcos de datos que no son demasiado grandes es (basada en la respuesta de @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
Alternativamente, también puede utilizar:
names(x) <- c("C","w","D") > x C w D 1 1 2 3
Además, también puede cambiar el nombre de un subconjunto de los nombres de las columnas:
names(x)[2:3] <- c("E","F") > x C E F 1 1 2 3
fuente
Esta es la forma más eficiente que he encontrado para cambiar el nombre de varias columnas usando una combinación de
purrr::set_names()
y algunasstringr
operaciones.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
fuente
~
y.
en laset_names()
tubería.purrr::set_names()
.purrr
funciones, la tilde~
significa "para cada columna". La.
sintaxis is dplyr para LHS = lado izquierdo de la tubería, es decir, la referencia al objeto que se canaliza, en este casodata
.Así que recientemente me encontré con esto yo mismo, si no está seguro de si las columnas existen y solo desea cambiar el nombre de las que sí lo hacen:
fuente
Sobre la base de la respuesta de @ 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
Esto no dependerá de un orden específico de columnas en el
x
conjunto de datos.fuente
match
se encarga de eso. Lo mejor que vas a hacer es probablemente lasetnames
respuesta de @ mnel .match
sigue siendo un comando orientado a la posición. Con este espíritu, consideré que la posición de respuesta de @ user3114046 también se basaba (incluso aunque el%in%
comando se encarga (o intenta) de las cosas). Por supuesto, supongo que puede argumentar que todos los comandos están orientados a la posición cuando profundizamos en el mecanismo de bajo nivel ... pero eso no es lo que quiero decir ... la respuesta de data.table es excelente porque no hay llamadas múltiples delname
comandos.Esto cambiaría todas las apariciones de esas letras en todos los nombres:
names(x) <- gsub("q", "A", gsub("e", "B", names(x) ) )
fuente
gsubfn
respuesta. Quizás venga G. Grothendieck. Él es el regex-meister.names(x)[names(x) %in% c("q","e")]<-c("A","B")
fuente
oldnames
está ordenada para queoldnames[i]
ocurra antesoldnames[j]
para i <j.Puede configurar el nombre, guardarlo como una lista y luego hacer su cambio de nombre masivo en la cadena. Un buen ejemplo de esto es cuando está haciendo una transición larga a amplia en un conjunto de datos:
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" "
fuente
Nota al margen, si desea concatenar una cadena a todos los nombres de columna, puede usar este simple código.
colnames(df) <- paste("renamed_",colnames(df),sep="")
fuente
Si la tabla contiene dos columnas con el mismo nombre, el código es el siguiente:
fuente
Puede utilizar un vector con nombre.
Con base R (quizás algo torpe):
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
O una
dplyr
opción con!!!
: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
Este último funciona porque el operador 'big-bang'
!!!
está forzando la evaluación de una lista o un vector.?`!!`
fuente
!!!oldnames
devuelve,c("A", "B")
pero ¿en qué lógica se transforma estoc("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))
. Creo que agregaré esta explicación a la respuesta. Saludos por mencionarloMuchas respuestas, así que escribí la función para que puedas copiar / pegar.
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
fuente
rename(x, c("q", "e"), c("Q", "E"))
ya no parece funcionar en dplyr renombrar?Si una fila de los datos contiene los nombres a los que desea cambiar todas las columnas, puede hacerlo
Dado
data
es su marco de datos yrow
es el número de fila que contiene los nuevos valores.Luego puede eliminar la fila que contiene los nombres con
fuente
Esta es la función que necesita: luego simplemente pase la x en un cambio de nombre (X) y cambiará el nombre de todos los valores que aparecen y si no está allí, no se producirá un error
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) }
fuente