Есть ли простой способ ранжировать по нескольким критериям, которые сохраняют связи в R?
Когда один критерий хорошо упорядочен, функция ранга возвращает очевидную вещь:
rank(c(2,4,1,3,5))
[1] 2 4 1 3 5
Когда у одного критерия есть связи, функция рангов (по умолчанию) присваивает средним рангам связей:
rank(c(2,4,1,1,5))
[1] 3.0 4.0 1.5 1.5 5.0
Функция рангов не позволяет сортировать по нескольким критериям, поэтому вам нужно использовать что-то еще. Один из способов сделать это - использовать совпадение и порядок. Для одного критерия без связей результаты одинаковы:
rank(c(2,4,1,3,5))
[1] 2 4 1 3 5
match(1:5, order(c(2,4,1,3,5)))
[1] 2 4 1 3 5
Однако для одного критерия со связями результаты отличаются:
rank(c(2,4,1,4,5))
[1] 2.0 3.5 1.0 3.5 5.0
match(1:5, order(c(2,4,1,4,5)))
[1] 2 3 1 4 5
Связи разбиваются таким образом, что связанные элементы сохраняют свой первоначальный порядок, а не присваиваются равные ранги. Эта функция, очевидно, обобщается при сортировке по нескольким критериям:
match(1:5, order(c(2,4,1,4,5),c(10,11,12,11,13)))
[1] 2 3 1 4 5
Наконец, вопрос: есть ли простой или встроенный способ вычисления ранга, используя несколько критериев, которые сохраняют связь? Я написал функцию, чтобы сделать это, но это уродливо и кажется смехотворно сложным для такой базовой функциональности...
Ответы
Ответ 1
interaction
делает то, что вам нужно:
> rank(interaction(c(2,4,1,4,5),c(10,11,12,11,13), lex.order=TRUE))
[1] 2.0 3.5 1.0 3.5 5.0
Вот что происходит.
interaction
ожидает факторов, поэтому векторы принудительно. Таким образом, получается порядок в уровнях факторов, как указано sort.list
, что для numeric
является численно неубывающим порядком.
Затем, чтобы объединить два фактора, взаимодействие создает уровни факторов, меняя второй аргумент быстрее (потому что lex.order=TRUE
). Таким образом, связи в первом векторе разрешаются значением во втором векторе (если возможно).
Наконец, rank
заставляет результирующий фактор numeric
.
Что на самом деле занимает место:
> as.numeric(interaction(c(2,4,1,4,5),c(10,11,12,11,13), lex.order=TRUE))
[1] 5 10 3 10 16
Вы сохраните некоторую память, если вы поставьте опцию drop=TRUE
на interaction
. Это изменит ранжированные числовые значения, но не их порядок, поэтому конечный результат будет таким же.