Сортировка R фрейма данных в указанном порядке

#r #sorting

#r #сортировка

Вопрос:

Предположим, у меня есть (очень простой пример):

 df <- data.frame(factor_name  = c("fac_Y", "fac_Y", "fac_Y", "fac_X", "fac_X", "fac_X", "fac_X", "fac_X", "fac_X"),
                 factor_level = c("cherry", "apple", "peach", 2, 1, 3, 4, 6, 8),
                 value        = c(1, 3, 2, 6, 3, 4, 1, 5, 2))
  

Мне нужно отсортировать, df основываясь на factor_name и factor_level не полагаясь на алфавитный / числовой порядок (потому что в более сложном случае, над которым я работаю, порядок сортировки совершенно не связан с этими вещами), так что:

(i) factor_name должен быть отсортирован как (fac_X, fac_Y)

(ii) внутри fac_X порядок factor_level сортировки должен быть (1, 2, 3, 4, 6, 8)

(iii) внутри fac_Y порядок factor_level сортировки должен быть ("apple", "peach", "cherry")

Итак, мне нужно будет вручную предоставить информацию о желаемом порядке (т. Е. (i)- (iii) выше), но я не уверен, как это сделать.

Поэтому я хотел бы, чтобы мой вывод был:

 df_sorted <- data.frame(factor_name  = c("fac_X", "fac_X", "fac_X", "fac_X", "fac_X", "fac_X", "fac_Y", "fac_Y", "fac_Y"),
                        factor_level = c(1, 2, 3, 4, 6, 8, "apple", "peach", "cherry"),
                        value        = c(3, 6, 4, 1, 5, 2, 3, 2, 1))
  

Кто-нибудь может помочь, пожалуйста?
Спасибо.

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

1. Это также может работать: df[order(df$factor_name,df$factor_level,df$value),]

Ответ №1:

Вы можете использовать match после определения correct_order .

 library(dplyr)

correct_order <- c(1, 2, 3, 4, 6, 8, "apple", "peach", "cherry")
df %>% arrange(factor_name, match(factor_level, correct_order))

#  factor_name factor_level value
#1       fac_X            1     3
#2       fac_X            2     6
#3       fac_X            3     4
#4       fac_X            4     1
#5       fac_X            6     5
#6       fac_X            8     2
#7       fac_Y        apple     3
#8       fac_Y        peach     2
#9       fac_Y       cherry     1
  

Вы могли бы использовать то же самое в базовом R order :

 df[with(df, order(factor_name, match(factor_level, correct_order))), ]
  

Обратите внимание, что не важно, что correct_order должны иметь значения для "fac_X" first и then "fac_Y" . Это может быть в любом порядке при условии сохранения значений между собой. Таким образом, приведенные выше ответы дали бы тот же результат с :

 correct_order <- c("apple", "peach", "cherry", 1, 2, 3, 4, 6, 8)
  

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

1. Я думаю, что это работает (и все еще работает в более сложном примере, который я только что попробовал). Спасибо.

Ответ №2:

Мы могли бы использовать factor с levels указанным

 library(dplyr)
df %>% 
  arrange(factor_name, factor(factor_level,
      levels = c(1, 2, 3, 4, 6, 8, 'apple', 'peach', 'cherry')))
#   factor_name factor_level value
#1       fac_X            1     3
#2       fac_X            2     6
#3       fac_X            3     4
#4       fac_X            4     1
#5       fac_X            6     5
#6       fac_X            8     2
#7       fac_Y        apple     3
#8       fac_Y        peach     2
#9       fac_Y       cherry     1
  

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

1. Разве это не зависит от возможности сортировки fac_Y в том же порядке, что и fac_X ? В общем, я не смогу сделать это предположение здесь. Каждый фактор будет иметь свой собственный конкретный порядок.

2. @Alan У вас совершенно разные уровни или у вас есть случай, когда один из них следует в направлении, противоположном другому

3. Совершенно другой — изменит OP, чтобы показать более четко

4. Ах да, хорошо, теперь я понимаю логику. Я поиграю с этим еще немного завтра. Спасибо.