如何使用第二个向量作为平局来对向量进行排名?

问题描述 投票:2回答:3

我需要为数字向量实现排名算法。我不知道是否可以使用R中的rank(),order()或sort()之类的功能来实现它,或者我是否应该对其进行硬编码。无论哪种方式,我都无法做到。

该算法的工作原理如下:

让x =(x_1,x_2 ...,x_n)和y =(y_1,y_2,... y_n)是两个向量。我们需要通过以下方式构建由x的排名元素组成的向量z:

  1. If x_i < x_j then z_i < z_j

  2. If x_i = x_j then

    • z_i < z_j if y_i < y_j
    • z_i > z_j if y_i > y_j
    • z_i = z_j if y_i = y_j
  3. If x_i is NA (missing) then

    • z_i > z_j if z_j is not NA
    • z_i = z_j if z_j is NA

例如,如果x =(30,15,27,49,15)且y =(12,11,10,9,8),则z =(4,2,3,5,1)

[我想我可以使用order(order(x,y, na.last=T)),实际上,只要x中的关系不与y相同,它就可以工作。如果是这种情况,那么order()会将它们按出现顺序排列,而不是让它们束缚。

例如,如果x =(30,15,27,49,15)且y =(12,8,10,9,8),则order(order(x,y, na.last=T))将输出z =(4,1,3,5, 2)代替z =(4,1,3,5,1)或另一个尊重步骤2的z(例如(3,1,2,4,1))。

我无法逃脱。我该如何进行?

r sorting ranking
3个回答
1
投票

[不幸的是,rank不提供使用第二个向量打破平局的能力(ordersort do允许的有用能力)。

但是library(data.table)提供了frank(),可以很好地完成工作。

x = c(30,15,27,49,15) 
y = c(12,11,10,9,8) 
frank(data.table(x,y), ties.method = "min")
# [1] 4 2 3 5 1

在R中,一个简单的解决方法如下所示(尽管请注意最后的警告):

x = c(30,15,27,49,15) 
y = c(12,11,10,9,8) 

rank(x*1e14 + y, ties.method = 'min')
# [1] 4 2 3 5 1

也用第二个示例进行测试

x = c(30,15,27,49,15) 
y = c(12,8,10,9,8)

rank(x*1e14+y, ties.method = 'min')
# [1] 4 1 3 5 1

当然,这仅在您的数据不太大(与我使用的大量1e14相比)时才有效。

也可以在基数R中将每个固定宽度的字符串表示形式粘贴在一起,然后对组合的字符向量进行排序。

rank(paste(
      formatC(x, width = 15, flag = "0"), 
      formatC(y, width = 15, flag = "0")), 
     ties.method = 'min')

0
投票

您可以编写函数来执行此操作:

my_order <- function(x,y){
  a <- rank(x,ties.method = "first")
  b <- `class<-`(names(which(table(x)>1)),class(x))
  c(apply(outer(x,b,'=='),2,function(m)a[m]<<-a[m][rank(y[m])]))
  a
}

apply函数的原因是因为我们可以有多个重复值:

x = c(30,15,27,49,15) ;
y = c(12,8,10,9,8) 
my_order(x,y)
[1] 4 1 3 5 1

my_order(c(2,1,1,2),c(6,4,2,6))
[1] 3 2 1 3

与]比较>

order(order(c(2,1,1,2),c(6,4,2,6)))
[1] 3 2 1 4

0
投票

使用data.table的选项:

© www.soinside.com 2019 - 2024. All rights reserved.