计算精英运动员比赛结果数据框中获胜时间的百分比

时间:2015-03-29 22:30:02

标签: r dplyr percentage

我为精英高山滑雪运动员创造了一个数据框架,用于跨越四年的世界杯赛。我正在使用dplyr并按比赛ID对比赛进行分组,由运动员按升序排列比赛结果(从头到尾),并将完成时间转换为分钟。

我现在想要创建一个名为Percent.From.Winning.Time的新变量,该变量将使每个完成时间相对于该特定比赛的获胜时间(即第一名终结者最终得到的值为100,并且休息时获胜时间的百分比小于100。例如,假设某场比赛的获胜时间为120秒,而第二名的比赛时间为121秒。我会计算:[1 - ((121-120)/ 120)] * 100 = 99.16。

请注意,我还指定了非完成时间(例如运动员被取消资格或未完成)作为NA。

以下是一些示例数据:

Raceid=c(1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2)
Athleteid=c(45, 21, 56, 64, 10, 76, 88, 91, 23, 13, 123, 2, 87, 91)
Position = c(1, 2, 3, 4, 5, NA, NA, 1, 2, 3, 4, NA, NA, NA)
Timetot3= c(144, 143, 142, 141, 140, NA, NA, 123, 122, 121, 120, NA, NA, NA)
WC.race.results=cbind(Raceid, Athleteid, Position, Timetot3)

有没有人有关于如何在dplyr中编写函数来生成这个新变量Percent.From.Winning.Time的建议或解决方案?

非常感谢您的考虑。

马特

3 个答案:

答案 0 :(得分:3)

这是一个data.table解决方案:

library(data.table)

setDT(WC.race.results)[
        ,wt:=(1-(Timetot3-in(Timetot3,na.rm=TRUE))/min(Timetot3,na.rm=TRUE))*100,
        Raceid]

#    Raceid Athleteid Position Timetot3        wt
# 1:      1        45        1      144  97.14286
# 2:      1        21        2      143  97.85714
# 3:      1        56        3      142  98.57143
# 4:      1        64        4      141  99.28571
# 5:      1        10        5      140 100.00000
# 6:      1        76       NA       NA        NA
# 7:      1        88       NA       NA        NA
# 8:      2        91        1      123  97.50000
# 9:      2        23        2      122  98.33333
# 10:     2        13        3      121  99.16667
# 11:     2       123        4      120 100.00000
# 12:     2         2       NA       NA        NA
# 13:     2        87       NA       NA        NA
# 14:     2        91       NA       NA        NA

答案 1 :(得分:3)

使用dplyr的一种方法是;

group_by(mydf, Raceid) %>%
mutate(Percent = (1 - (Timetot3 - min(Timetot3, na.rm = TRUE)) / min(Timetot3, na.rm = TRUE)) * 100)

#   Raceid Athleteid Position Timetot3   Percent
#1       1        45        1      144  97.14286
#2       1        21        2      143  97.85714
#3       1        56        3      142  98.57143
#4       1        64        4      141  99.28571
#5       1        10        5      140 100.00000
#6       1        76       NA       NA        NA
#7       1        88       NA       NA        NA
#8       2        91        1      123  97.50000
#9       2        23        2      122  98.33333
#10      2        13        3      121  99.16667
#11      2       123        4      120 100.00000
#12      2         2       NA       NA        NA
#13      2        87       NA       NA        NA
#14      2        91       NA       NA        NA

DATA

mydf <- data.frame(Raceid=c(1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2),
                   Athleteid=c(45, 21, 56, 64, 10, 76, 88, 91, 23, 13, 123, 2, 87, 91),
                   Position = c(1, 2, 3, 4, 5, NA, NA, 1, 2, 3, 4, NA, NA, NA),
                   Timetot3= c(144, 143, 142, 141, 140, NA, NA, 123, 122, 121, 120, NA, NA, NA))

答案 2 :(得分:0)

这是更长,但至少是无包装解决方案:

WC.race.results=data.frame(Raceid, Athleteid, Position, Timetot3)    
results.split <- by(WC.race.results, WC.race.results$Raceid, function(race) {
  win <- min(race$Timetot3, na.rm=TRUE)
  cbind(race, wt=(1-((race$Timetot3-win)/race$Timetot3))*100)
})
WC.race.results <- do.call(rbind, results.split)

我非常确定有一种方法可以改善这一点,可能使用dplyr本身,但我认为这是一个开始。

修改

已经有一个dplyr答案了,无论如何我都会离开我的。