Как сортировать жала в алфавитном и числовом порядке?

#r

Вопрос:

У меня есть вектор строк, которые я хочу отсортировать в алфавитном порядке, а затем отсортировать по номеру, который находится в конце строк. Конечный результат должен быть "AGSHIM1", "AGSHIU1", "AGSHIZ1","AGSHIH2", "AGSHIM2","AGSHIU2", "AGSHIZ2"

 d<-c("AGSHIZ2", "AGSHIZ1", "AGSHIU1", "AGSHIM1", "AGSHIH2", "AGSHIM2", 
"AGSHIU2")
d[order(d,as.numeric(substr(d, nchar(d), nchar(d))))]

>"AGSHIH2" "AGSHIM1" "AGSHIM2" "AGSHIZ1" "AGSHIZ2" "AGSHIU1" "AGSHIU2"
 

Ответ №1:

Что вы можете сделать, так это отделить число от строки и сначала отсортировать по номеру, а затем внутри каждой группы чисел отсортировать в алфавитном порядке:

 sortSpecial <- function(d) {
  df <- data.frame(
    original = d,
    chars = gsub("[[:digit:]]", "", d),
    nums = gsub("[^[:digit:]]", "", d)
  )
  df <- df[with(df, order(nums, chars)),]
  return(df$original)
}


d <- sortSpecial(d)

d
# [1] "AGSHIM1" "AGSHIU1" "AGSHIZ1" "AGSHIH2" "AGSHIM2" "AGSHIU2" "AGSHIZ2"
 

Должен быть более элегантный подход, я просто этого не знаю. Тем не менее, дайте мне знать, если это поможет.

Обновить
Я не мог не вдохновиться подходом Картика С. Если вы не хотите сначала генерировать функцию, вы можете выполнить те же действия, что и перед использованием dplyr:

 library(dplyr)
d <- data.frame(d = d) %>% 
  mutate(
    chars = gsub("[[:digit:]]", "", d),
    nums = gsub("[^[:digit:]]", "", d)
  ) %>% 
  arrange(nums, chars) %>% 
  pull(d)
 

Опять же, шаги идентичны, поэтому выбор подхода является вопросом предпочтения.

Ответ №2:

Другой подход. Но я уверен, что, скорее всего, существует более короткое решение.

 library(dplyr)
library(stringr)
library(tibble)
d %>% as.tibble() %>% 
   transmute(dig = str_extract(value,'\d'), ltrs = str_remove(value, '\d')) %>% type.convert(as.is = 1) %>% 
     arrange(dig,ltrs) %>% transmute(d = str_c(ltrs,dig, sep = '')) %>% pull(d)
[1] "AGSHIM1" "AGSHIU1" "AGSHIZ1" "AGSHIH2" "AGSHIM2" "AGSHIU2" "AGSHIZ2"
 

Комментарии:

1. Просто комментарий, я считаю, что если вы используете mutate вместо первого transmute , то вам не понадобится вторая transmute операция. Однако вам нужно было бы pull(value) вместо pull(d) этого.

Ответ №3:

Вот один базовый вариант R, использующий gsub order

 > d[order(as.numeric(gsub("\D", "", d)), d)]
[1] "AGSHIM1" "AGSHIU1" "AGSHIZ1" "AGSHIH2" "AGSHIM2" "AGSHIU2" "AGSHIZ2"