Подтвердить что ты не робот

Есть ли простой способ ранжировать по нескольким критериям, которые сохраняют связи в 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

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

4b9b3361

Ответ 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. Это изменит ранжированные числовые значения, но не их порядок, поэтому конечный результат будет таким же.