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

Calculating percent from winning time in data frame of race results for elite athletes

我为四年期间所有世界杯比赛的精英高山滑雪者创建了比赛结果数据框。我正在使用 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?

非常感谢您的考虑。

马特

这里有一个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

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

数据

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))

这是一个长得多但至少是无包的解决方案:

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答案了,我还是留下我的吧。