R 基于多个变量计算具有联系的排名

R 基于多个变量计算具有联系的排名,r,ranking,R,Ranking,我正在计算一个体育项目的奖牌表 我的数据如下所示: test <- data.frame("ID" = c("1_1", "1_2", "1_3", "1_4","1_5","1_6"), "gold"=c(10, 4, 1, 7, 7, 1), "silver"=c(1, 3, 2, 19, 19, 2), "bronze"=c(1, 8, 2, 0, 0, 2)) 另外,

我正在计算一个体育项目的奖牌表

我的数据如下所示:

test <- data.frame("ID" = c("1_1", "1_2", "1_3", "1_4","1_5","1_6"),
                   "gold"=c(10, 4, 1, 7, 7, 1),
                   "silver"=c(1, 3, 2, 19, 19, 2),
                   "bronze"=c(1, 8, 2, 0, 0, 2))
另外,
交互
未成功:

as.numeric(interaction(gl(-test$gold), gl(-test$silver), gl(-test$bronze), lex.order = TRUE))
你知道如何基于多个变量计算排名吗


用亨里克的想法解决:

as.data.frame(setDT(test)[ , rank := frank(test, -gold, -silver, -bronze, ties.method = "min")]; setorder(test, rank))

您可以使用相当于
base::rank
frank
data.table
frank
的一个很好的特性是,它不仅接受向量(如
rank
中的向量),还接受
data.frame
data.table
作为输入。对于这些类型的对象,排名可能基于多个列

使用原始的
数据帧

test$rank <- data.table::frank(test, -gold, -silver, -bronze, ties.method = "min")

基本的R解决方案是:

test <- data.frame("ID"=c("1_1", "1_2", "1_3", "1_4","1_5","1_6"), 
                   "gold"=c(10,4,1,7,7,1), 
                   "silver"=c(1,3,2,19,19,2), 
                   "bronze"=c(1,8,2,0,0,2))

(test_ordered<-with(test, test[order(-gold,-silver,-bronze),]))

roll.any.greater <- function (mat) {
  mat.lead <- head(mat, -1)
  mat.lag <- tail(mat, -1)
  result <- rep(1, nrow(mat.lead) + 1)
  for (i in (2:length(result))) {
    result[i] <- ifelse(any(as.logical(abs(mat.lead[i-1, ] - mat.lag[i-1, ]))) != FALSE,
                        i, result[i-1])
  }
  return(result)
}
(want <- cbind(test_ordered,
               rank =
               roll.any.greater(test_ordered[colnames(test_ordered) %in% c("gold", "silver", "bronze")])))

test如果你对奖牌的最大数量有一个很好的了解,你可以做一些类似于
test\u的事情。这个主意不错,有点粗糙,但也很有效。相关:
as.data.frame(setDT(test)[ , rank := frank(test, -gold, -silver, -bronze, ties.method = "min")]; setorder(test, rank))
test$rank <- data.table::frank(test, -gold, -silver, -bronze, ties.method = "min")
setDT(test)[ , rank := frank(test, -gold, -silver, -bronze, ties.method = "min")]
setorder(test, rank)
test <- data.frame("ID"=c("1_1", "1_2", "1_3", "1_4","1_5","1_6"), 
                   "gold"=c(10,4,1,7,7,1), 
                   "silver"=c(1,3,2,19,19,2), 
                   "bronze"=c(1,8,2,0,0,2))

(test_ordered<-with(test, test[order(-gold,-silver,-bronze),]))

roll.any.greater <- function (mat) {
  mat.lead <- head(mat, -1)
  mat.lag <- tail(mat, -1)
  result <- rep(1, nrow(mat.lead) + 1)
  for (i in (2:length(result))) {
    result[i] <- ifelse(any(as.logical(abs(mat.lead[i-1, ] - mat.lag[i-1, ]))) != FALSE,
                        i, result[i-1])
  }
  return(result)
}
(want <- cbind(test_ordered,
               rank =
               roll.any.greater(test_ordered[colnames(test_ordered) %in% c("gold", "silver", "bronze")])))