R:具有两个变量和 ties.method 随机的秩函数
R: Rank-function with two variables and ties.method random
R 中有没有一种方法可以使用具有多个条件和 ties.method 的排名函数(或类似函数)?
通常排名用于对向量中的值进行排名,如果有联系,您可以使用联系方法之一("average"、"random"、"first"、... ).但是当对矩阵中的列进行排名时,我想使用多列 和 一种联系方法。
一个最小的例子:
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
值进行排序。但如果有关系,我希望函数查看 z
值。如果在那之后仍然有联系,那么我想使用 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
-函数(即 m[order(m[,2], m[,3], sample(length(x))),]
获得上述结果,但我想接收排名值,而不是排序矩阵的索引。
如果您需要详细说明为什么我需要排名值,请随时提问,我将使用更多详细信息编辑问题。现在我认为最小的例子就可以了。
编辑: 如@alistaire 指出的那样,将数据帧更改为矩阵。
对不起,我最初误解了你的问题。我认为这就是你想要的。我做了一个小改动。具体来说,我让你的变量 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
您可以使用排名中可用的任何平局方法,但我在这里选择使用 "last" 以强调它会改变顺序。
由于 order(order(x))
给出与 rank(x)
相同的结果(参见 ),您可以只做
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
使用 data.table
的 frankv
功能怎么样?
library(data.table)
rank <- frankv(list(m[,"y"], m[,"z"]), ties.method = "random")
m <- m[order(rank),]
R 中有没有一种方法可以使用具有多个条件和 ties.method 的排名函数(或类似函数)?
通常排名用于对向量中的值进行排名,如果有联系,您可以使用联系方法之一("average"、"random"、"first"、... ).但是当对矩阵中的列进行排名时,我想使用多列 和 一种联系方法。
一个最小的例子:
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
值进行排序。但如果有关系,我希望函数查看 z
值。如果在那之后仍然有联系,那么我想使用 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
-函数(即 m[order(m[,2], m[,3], sample(length(x))),]
获得上述结果,但我想接收排名值,而不是排序矩阵的索引。
如果您需要详细说明为什么我需要排名值,请随时提问,我将使用更多详细信息编辑问题。现在我认为最小的例子就可以了。
编辑: 如@alistaire 指出的那样,将数据帧更改为矩阵。
对不起,我最初误解了你的问题。我认为这就是你想要的。我做了一个小改动。具体来说,我让你的变量 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
您可以使用排名中可用的任何平局方法,但我在这里选择使用 "last" 以强调它会改变顺序。
由于 order(order(x))
给出与 rank(x)
相同的结果(参见
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
使用 data.table
的 frankv
功能怎么样?
library(data.table)
rank <- frankv(list(m[,"y"], m[,"z"]), ties.method = "random")
m <- m[order(rank),]