Как сделать вид смешанных значений в 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