我正在尝试为体育赛事计算奖牌表。
我的数据如下:
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))
首先,我想根据&#34; gold&#34;,&#34; silver&#34;和&#34; bronze&#34;的数量订购数据,如下所示:
(test_ordered <- with(test, test[order(-gold, -silver, -bronze), ]))
然后计算最终的奖牌排名。这就是最终排名列应该如何:
(test_ordered$rank<-c(1, 2, 2, 4, 5, 5))
# ID gold silver bronze rank
# 1 1_1 10 1 1 1
# 4 1_4 7 19 0 2
# 5 1_5 7 19 0 2
# 2 1_2 4 3 8 4
# 3 1_3 1 2 2 5
# 6 1_6 1 2 2 5
作为ID&#34; 1_4&#34;和&#34; 1_5&#34;获得与他们分享排名2的奖牌相同的组合,例如
我在rank
(也dplyr::min_ranked
)使用两个以上条件的尝试失败了:
with(test, rank(-gold, -silver, -bronze, ties.method = "min"))
# (...) unused argument (-bronze)
interaction
也没有成功:
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))
答案 0 :(得分:3)
您可以使用data.table
等效的base::rank
,frank
。 frank
的一个不错的功能是,它不仅接受向量(如rank
),还接受data.frame
或data.table
作为输入。对于这些类型的对象,排名可以基于几列。
使用原始data.frame
:
test$rank <- data.table::frank(test, -gold, -silver, -bronze, ties.method = "min")
或者,如果您想全身心投入data.table
个功能:
setDT(test)[ , rank := frank(test, -gold, -silver, -bronze, ties.method = "min")]
setorder(test, rank)
答案 1 :(得分:0)
基础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")])))