¿Cómo ordenar un vector de caracteres donde los elementos contienen letras y números en R?

Tengo una matriz de caracteres

cf <- c("V440","V457","V116","V327","V446","V108", "V155","V217","V120","V51","V477") 

Me gustaría ordenarlo en orden descendente para que tenga un resultado como este:

 V51 V108 V116 V120 V155 V217 V327 V440 V446 V457 V477 

He intentado sort.list() como este

 cf[sort.list(cf)] 

y obtuve esta respuesta:

 [1] "V108" "V116" "V120" "V155" "V217" "V327" "V440" "V446" "V457" "V477" "V51" 

y también intenté order() y obtuve el mismo resultado.

Puede alguien ayudarme por favor

Pruebe mixedsort del paquete “gtools”:

 > # install.packages("gtools") ## Uncomment if not already installed > library(gtools) > mixedsort(cf) [1] "V51" "V108" "V116" "V120" "V155" "V217" "V327" "V440" "V446" "V457" "V477" 

Si no desea usar mixedsort (no estoy seguro de por qué uno no), y si su vector tiene un patrón bastante consistente (por ejemplo, letras seguidas de números), también es probable que pruebe algo como esto. (Nota: relativamente no probado )

 newvec < - c("V440", "V457", "V116", "V327", "V446", "V108", "V155", "V217", "V120", "V51", "V477", "B22", "A10", "Z01") newvec[order(gsub("([AZ]+)([0-9]+)", "\\1", newvec), as.numeric(gsub("([AZ]+)([0-9]+)", "\\2", newvec)))] # [1] "A10" "B22" "V51" "V108" "V116" "V120" "V155" "V217" "V327" "V440" # [11] "V446" "V457" "V477" "Z01" 

Muchas respuestas correctas aquí, esta es otra forma, solo por diversión.

 cf[order(nchar(cf), cf)] # [1] "V51" "V108" "V116" "V120" "V155" "V217" "V327" "V440" "V446" "V457" "V477" 

Simplemente raspe el carácter “V” anterior para construir un vector de clasificación. No se requieren herramientas sofisticadas adicionales.

 vals < - as.numeric(gsub("V","", cf)) cf[order(vals)] [1] "V51" "V108" "V116" "V120" "V155" "V217" "V327" "V440" "V446" [10] "V457" "V477" 

R ordena correctamente las cadenas alfabéticamente, es por eso que obtienes ese resultado.

Además de la muy buena respuesta de @Ananda, si quieres usar la base R, puedes usar strsplit para eliminar la “V” de cada cadena y luego usar as.numeric para convertir las cadenas en enteros:

 vals < - as.numeric(sapply(cf, FUN=function(x){strsplit(x, "V")[[1]][2]})) 

Ahora puedes ordenar tus cadenas usando vals

 cf[order(vals)] 

Aquí hay un enfoque de base que utiliza names y sort (el de Ananda era bastante hábil):

 cf < - c("V440","V457","V116","V327","V446","V108", "V155","V217","V120","V51","V477") cf2 <- as.numeric(gsub("[^[:digit:]]", "", cf)) names(cf2) <- seq_along(cf2) cf[as.numeric(names(sort(cf2)))] ## > cf[as.numeric(names(sort(cf2)))] ## [1] "V51" "V108" "V116" "V120" "V155" "V217" "V327" ## [8] "V440" "V446" "V457" "V477" 

Una solución más en una línea de código que usa la función str_sort (del stringr stringr).

 # install.packages("stringr") ## Uncomment if not already installed library(stringr) 

str_sort(cf, numeric = TRUE)

 [1] "V51" "V108" "V116" "V120" "V155" "V217" "V327" "V440" "V446" "V457" "V477"