Как сделать вид смешанных значений в R

У меня есть фрейм данных, который я хочу отсортировать на один столбец, чем на следующий (при помощи tidyverse, если это возможно).

Я проверил адрес ниже, но решения, похоже, не работают.

Заказать "смешанный" вектор (цифры с буквами)

Пример кода для примера:

variable <- c("channel", "channel", "channel", "comp_ded", "comp_ded", "comp_ded")
level <- c("DIR", "EA", "IA", "500", "750", "1000")
df <- as_tibble(cbind(variable, level))

Это не дает мне то, что я хочу:

df <- df %>% arrange(variable, level)

Порядок столбцов уровня выглядит следующим образом:

variable level channel DIR channel EA channel IA level 1000 level 500 level 750

Они нужны мне:

variable level channel DIR channel EA channel IA level 500 level 750 level 1000

В реальном наборе данных есть несколько разных "переменных", где половина должна быть отсортирована по порядку номеров, а половина - по алфавиту. Кто-нибудь знает как это сделать?

6 ответов

Решение

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

df <- bind_rows(df %>%
              filter(!is.na(as.numeric(level))) %>%
              arrange(variable, as.numeric(level)),
          df %>%
              filter(is.na(as.numeric(level))) %>%
              arrange(variable, level))

Дает тебе:

# A tibble: 6 x 2
  variable level
  <chr>    <chr>
1 comp_ded 500  
2 comp_ded 750  
3 comp_ded 1000 
4 channel  DIR  
5 channel  EA   
6 channel  IA   

Самое простое решение было бы использовать dplyr::group_by,

library(dplyr)

variable <- c("channel", "channel", "channel", "comp_ded", "comp_ded", "comp_ded")
level <- c("DIR", "EA", "IA", "500", "750", "1000")
df <- as_tibble(cbind(variable, level))

df %>%
  group_by(variable, level) %>%
  arrange()

# A tibble: 6 x 2
  variable  level
     <chr> <fctr>
1 comp_ded    DIR
2 comp_ded     EA
3 comp_ded     IA
4  channel    500
5  channel    750
6  channel   1000

С помощью gtoolsнемного более короткое решение, которое использует mixedorder:

library(gtools)
sorteddf <- df[with(df, order(variable, mixedorder(level))),]

Выход:

  variable level
1 channel  DIR  
2 channel  EA   
3 channel  IA   
4 comp_ded 500  
5 comp_ded 750  
6 comp_ded 1000

Преобразовать в фактор и изменить уровни. Еще проще с forcats::fct_relevel()

# Convert to factor
df <- as_tibble(cbind(variable, level)) %>%
  mutate(level = as.factor(level))

# Change order of levels
levels(df$level) = levels(df$level)[match(c("DIR", "EA", "IA", "500", "750", "1000"), levels(df$level))]

df %>% arrange(level)

# A tibble: 6 x 2
  variable  level
     <chr> <fctr>
1 comp_ded    DIR
2 comp_ded     EA
3 comp_ded     IA
4  channel    500
5  channel    750
6  channel   1000

Вы можете создать временную переменную для сортировки. После того, как вы отсортировали в нужном порядке, вы также можете установить порядок навсегда, преобразовав его в множитель (как в ответе @Vio). Может быть, что-то вроде этого:

df = df %>% 
  mutate(tmp = as.numeric(level)) %>% 
  arrange(variable, tmp, level) %>% 
  select(-tmp) %>% 
  mutate(level = factor(level, levels=unique(level)))
  variable level
  <chr>    <fct>
1 channel  DIR  
2 channel  EA   
3 channel  IA   
4 comp_ded 500  
5 comp_ded 750  
6 comp_ded 1000

Я думаю, что вы также можете сократить это, не создавая явную временную переменную, а вместо этого используя "анонимную" переменную внутри arrange:

df = df %>% 
  arrange(variable, as.numeric(level), level) %>% 
  mutate(level = factor(level, levels=unique(level)))

Думаю, отсортировать по as.numeric(level) сначала, затем level:

      df %>% arrange(variable, as.numeric(level), level)

Дает:

      # A tibble: 6 x 2
variable level
<chr>    <chr>
1 channel  DIR
2 channel  EA
3 channel  IA
4 comp_ded 500
5 comp_ded 750
6 comp_ded 1000 
Другие вопросы по тегам