【问题标题】:R: Rank-function with two variables and ties.method randomR:具有两个变量和关系的秩函数。随机方法
【发布时间】:2017-05-04 00:31:54
【问题描述】:

在 R 中有没有一种方法可以使用具有多个条件和 ties.method 的 rank 函数(或类似函数)?

通常排名用于对向量中的值进行排名,如果存在平局,您可以使用其中一种平局方法(“平均”、“随机”、“第一”等)。但是在对矩阵中的列进行排名时,我想使用多列其中一种关系方法。

一个最小的例子:

x <- c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
y <- c(1, 4, 5, 5, 2, 8 ,8, 1,3, 3)
z <- c(0.2, 0.8, 0.5, 0.4, 0.2, 0.1, 0.1, 0.7, 0.3, 0.3)
m <- cbind(x=x,y=y, z=z)

假设我想在上面的矩阵中对y-values 进行排名。但如果有关系,我希望函数查看z-values。如果在那之后仍然有联系,那么我想使用ties.method = "random"-参数。

换句话说,可能的结果是:

       x y   z
 [1,]  1 1 0.2
 [2,]  8 1 0.7
 [3,]  5 2 0.2
 [4,]  9 3 0.3
 [5,] 10 3 0.3
 [6,]  2 4 0.8
 [7,]  4 5 0.4
 [8,]  3 5 0.5
 [9,]  6 8 0.1
[10,]  7 8 0.1

但也可能是这样的:

       x y   z
 [1,]  1 1 0.2
 [2,]  8 1 0.7
 [3,]  5 2 0.2
 [4,] 10 3 0.3
 [5,]  9 3 0.3
 [6,]  2 4 0.8
 [7,]  4 5 0.4
 [8,]  3 5 0.5
 [9,]  7 8 0.1
[10,]  6 8 0.1

注意第四行和第五行的不同(就像第九行和第十行一样)。我已经能够使用order-function(即m[order(m[,2], m[,3], sample(length(x))),],但我想接收排名值,而不是排序矩阵的索引。

如果您需要详细说明我为什么需要排名值,请随时提问,我将编辑问题并提供更多详细信息。现在我认为最小的例子就可以了。

编辑:正如@alistaire 指出的那样,将数据框更改为矩阵。

【问题讨论】:

  • 为了澄清,cbind 制作了一个矩阵,而不是一个 data.frame。如果你想要一个 data.frame,请使用data.frame
  • @alistaire,你是对的,谢谢你的澄清!

标签: r ranking rank


【解决方案1】:

使用data.tablefrankv函数怎么样?

library(data.table)
rank <- frankv(list(m[,"y"], m[,"z"]), ties.method = "random")
m <- m[order(rank),]

【讨论】:

    【解决方案2】:

    由于order(order(x)) 给出与rank(x) 相同的结果(请参阅Why does order(order(x)) equal rank(x) in R?),您可以这样做

    order(order(y, z, runif(length(y))))
    

    获取排名值。


    这是一种更复杂的方法,允许您使用来自ties.method 的方法。它需要dplyr:

    library(dplyr)
    rank2 <- function(df, key1, key2, ties.method) {
      average <- function(x) mean(x)
      random <- function(x) sample(x, length(x))
      df$r <- order(order(df[[key1]], df[[key2]]))
      group_by_(df, key1, key2) %>% mutate(rr = get(ties.method)(r))  
    }
    
    rank2(df, "y", "z", "average")
    # Source: local data frame [10 x 5]
    # Groups: y, z [8]
    #        x     y     z     r    rr
    #    <dbl> <dbl> <dbl> <int> <dbl>
    # 1      1     1   0.2     1   1.0
    # 2      2     4   0.8     6   6.0
    # 3      3     5   0.5     8   8.0
    # 4      4     5   0.4     7   7.0
    # 5      5     2   0.2     3   3.0
    # 6      6     8   0.1     9   9.5
    # 7      7     8   0.1    10   9.5
    # 8      8     1   0.7     2   2.0
    # 9      9     3   0.3     4   4.5
    # 10    10     3   0.3     5   4.5
    

    【讨论】:

    • 这如何控制出现平局时发生的情况?
    • 我最终使用了您答案的第一部分。此外,使用runif(length(y)) 而不是sample(length(y)) 似乎效果更好。第二部分(dplyr)可能会在稍后阶段派上用场。谢谢!
    【解决方案3】:

    对不起,我最初误解了你的问题。我认为这就是你想要的。我做了一个小改动。具体来说,我将您的变量 df 设为数据框,而不仅仅是矩阵。

    x <- c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
    y <- c(1, 4, 5, 5, 2, 8 ,8, 1,3, 3)
    z <- c(0.2, 0.8, 0.5, 0.4, 0.2, 0.1, 0.1, 0.7, 0.3, 0.3)
    df <- data.frame(x=x,y=y, z=z)
    
    TM = "last"     ## Your desired ties method here.
    df[rank(df$z, ties.method=TM),] = df
    df = df[order(df$y),]
    df
        x y   z
    4   1 1 0.2
    9   8 1 0.7
    3   5 2 0.2
    5  10 3 0.3
    6   9 3 0.3
    10  2 4 0.8
    7   4 5 0.4
    8   3 5 0.5
    1   7 8 0.1
    2   6 8 0.1
    

    您可以使用排名中可用的任何 ties 方法,但我在这里选择使用“last”,以便强调它进行了顺序切换。

    【讨论】:

      猜你喜欢
      • 2017-06-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-17
      • 2014-10-24
      • 2020-01-30
      • 2021-01-07
      • 1970-01-01
      相关资源
      最近更新 更多