tl; dr: Я думаю, что версия 1 лучше. Версии 2 и 3 были ранними идеями, которые не так хороши, но я оставляю их здесь на случай, если они кому-нибудь пригодятся.
К сожалению rank
не дает возможности разорвать связи, используя секунду вектор (полезная возможность, которую позволяют order
и sort
do ).
Версия 1
Но, library(data.table)
обеспечивает frank()
, который прекрасно выполняет свою работу.
x = c(30,15,27,49,15)
y = c(12,11,10,9,8)
frank(list(x,y), ties.method = "min")
# [1] 4 2 3 5 1
x = c(30,15,27,49,15)
y = c(12,8,10,9,8)
frank(list(x,y), ties.method = "min")
# [1] 4 1 3 5 1
Обратите внимание, что frank
также предоставляет еще одну опцию для ties.method = "dense"
что может быть лучше для некоторых целей, поскольку не пропускает ранги (то есть, когда двум значениям присваивается ранг 1, следующий по величине получает ранг 2, а не 3) - см. пример ниже
frank(list(x,y), ties.method = "dense")
[1] 3 1 2 4 1
Версия 2
Если вы хотите придерживаться базы R, одним из простых обходных путей будет ранжирование x * K + y
, где K - любое число, достаточно большое, что добавление наибольшего y
к любому x*K
не может измениться. порядок:
ranky = function(x,y) {
K = 1 + max(y) / min(diff(sort(unique(x))))
rank(x*K + y, ties.method = 'min')
}
ranky(c(30,15,27,49,15), c(12,11,10,9,8) )
# [1] 4 2 3 5 1
ranky(c(30,15,27,49,15), c(12,8,10,9,8))
# [1] 4 1 3 5 1
Версия 3
Также в базе R вы можете вставить вместе строковые представления фиксированной ширины каждого и затем ранжировать объединенный символьный вектор.
rank(paste(
formatC(x, width = 15, flag = "0"),
formatC(y, width = 15, flag = "0")),
ties.method = 'min')