r - 如何按顺序更新评级?

标签 r for-loop apply rolling-computation accumulate

给定这个简单的数据集:

data <- data.frame(ID=seq(1:15),
                   H.team=c("GS","LAC","MIL","CHA","MIL","ATL","TOR","CHA","LAC","GS","TOR","MIL","ATL","CHA","TOR"),
                   A.team=c("MIL","CHA","TOR","ATL","GS","MIL","LAC","GS","TOR","ATL","CHA","LAC","GS","MIL","ATL"),
                   H.pts=c(94,120,91,84,88,96,93,95,113,85,101,116,86,102,90),
                   A.pts=c(84,107,99,75,90,105,87,99,94,87,92,106,84,89,89))
data
   ID H.team A.team H.pts A.pts
1   1     GS    MIL    94    84
2   2    LAC    CHA   120   107
3   3    MIL    TOR    91    99
4   4    CHA    ATL    84    75
5   5    MIL     GS    88    90
6   6    ATL    MIL    96   105
7   7    TOR    LAC    93    87
8   8    CHA     GS    95    99
9   9    LAC    TOR   113    94
10 10     GS    ATL    85    87
11 11    TOR    CHA   101    92
12 12    MIL    LAC   116   106
13 13    ATL     GS    86    84
14 14    CHA    MIL   102    89
15 15    TOR    ATL    90    89

我正在尝试为每个团队计算一个新的评分变量(rat),结果应该是:

   ID H.team A.team H.pts A.pts   h.rbef   a.rbef   h.raft   a.raft
1   1     GS    MIL    94    84 1500.000 1500.000 1508.487 1491.513
2   2    LAC    CHA   120   107 1500.000 1500.000 1510.021 1489.979
3   3    MIL    TOR    91    99 1491.513 1500.000 1481.066 1510.447
4   4    CHA    ATL    84    75 1489.979 1500.000 1498.279 1491.700
5   5    MIL     GS    88    90 1481.066 1508.487 1475.842 1513.711
6   6    ATL    MIL    96   105 1491.700 1475.842 1479.614 1487.928
7   7    TOR    LAC    93    87 1510.447 1510.021 1516.760 1503.708
8   8    CHA     GS    95    99 1498.279 1513.711 1491.164 1520.826
9   9    LAC    TOR   113    94 1503.708 1516.760 1517.357 1503.111
10 10     GS    ATL    85    87 1520.826 1479.614 1514.361 1486.079
11 11    TOR    CHA   101    92 1503.111 1491.164 1510.678 1483.597
12 12    MIL    LAC   116   106 1487.928 1517.357 1497.502 1507.783
13 13    ATL     GS    86    84 1486.079 1514.361 1490.516 1509.924
14 14    CHA    MIL   102    89 1483.597 1497.502 1494.213 1486.886
15 15    TOR    ATL    90    89 1510.678 1490.516 1513.711 1487.483

每个团队的第一个rat值为1500

比赛结束后,rat的值更新如下:

rat.after=rat.before+k*(S-E)

其中,如果球队获胜,则 S = 1,否则为 0

E是比赛开始前的比赛获胜概率,由以下函数定义:

win.probs<- function(h.rbef, a.rbef, hca=64) {
  h = 10^(h.rbef/400)
  a = 10^(a.rbef/400)
  hca = 10^(hca/400)
  den = a + hca*h
  h.prob = hca*h / den
  a.prob = a / den
  return(c(h.prob,a.prob))
}
#example (not run): win.probs(1500,1500)

k是一个移动常数,定义如下:

rat.k<- function(h.pts,a.pts,h.rbef,a.rbef) {
  ifelse(h.pts-a.pts>0,
         20*(h.pts-a.pts+3)^0.8/(7.5+0.006*(h.rbef-a.rbef)),
         20*(-(h.pts-a.pts)+3)^0.8/(7.5+0.006*(-(h.rbef-a.rbef))))
}
#example (not run): rat.k(94,84,1500,1500)

我编写了以下更新函数,它在单场比赛中运行良好:

up.rat<- function(h.pts, a.pts, h.rbef, a.rbef, hca=64) {
    h.prob = win.probs(h.rbef, a.rbef, hca)[1]
    a.prob = win.probs(h.rbef, a.rbef, hca)[2]
    h.win = ifelse(h.pts-a.pts>0,1,0)
    a.win = ifelse(h.pts-a.pts<0,1,0)
    k = rat.k(h.pts,a.pts,h.rbef,a.rbef)
    h.raft = h.rbef + k * (h.win - h.prob) 
    a.raft = a.rbef + k * (a.win - a.prob) 
  return(c(h.rbef,a.rbef,h.raft,a.raft))
}
#example (not run): up.rat(94,84,1500,1500)

并且,将其“手动”应用于我发现上面结果的数据。例如,第一场比赛是 GS 对阵 MIL:比赛前两队的评分均为 1500,比赛结束后主队的评分为 1500 1508.487,而客队则为 1491.513(零和评级)。因此,GS 将以更新后的评级开始下一场比赛,MIL 也是如此。

有人可以帮我找到一种方法来“自动”执行此操作,因为我的原始数据超过 15 行吗?我的自定义功能似乎运行良好,我发现这里真正具有挑战性的是更新评级,因为球队不需要在主场进行比赛,然后进行客场比赛:评级的值之前等于上一场比赛的之后评分,无论是主客场还是客场比赛。 另请注意,每支球队的比赛场数不必相同(例如,MIL 参加了 6 场比赛,LAC 参加了 4 场比赛,其他球队参加了 5 场比赛)。

感谢任何试图给我任何提示或帮助的人。

最佳答案

我们可以创建一个函数

f1 <- function(dat, start_val) {
       dat[c("h.rbef", "a.rbef", "h.raft", "a.raft")] <- start_val
       for(i in seq_len(nrow(data))) {
       
    
        if(i == 1) {
    
           h.rbef <- dat$h.rbef[1]
           a.rbef <- dat$a.rbef[1]
    
    
        } else {
    
          hh.ind <- with(dat, tail(which(H.team[seq_len(i-1)] %in% H.team[i]), 1))
          ha.ind <- with(dat, tail(which(A.team[seq_len(i-1)] %in% H.team[i]), 1))  
      
          aa.ind <- with(dat, tail(which(A.team[seq_len(i-1)] %in% A.team[i]), 1))
          ah.ind <- with(dat, tail(which(H.team[seq_len(i-1)] %in% A.team[i]), 1))
      
          if(length(hh.ind) > 0 & length(ha.ind) > 0 ) {
               ix <- which.max(c(hh.ind, ha.ind))
               mx <- max(hh.ind, ha.ind)
               if(ix == 1) {
                 h.rbef <- dat$h.raft[mx]
           
               } else {
                 h.rbef <- dat$a.raft[mx]
           
               }
      
          } else {
        
                 if(length(hh.ind) > 0) {
            
                 h.rbef <- dat$h.raft[hh.ind]
      
                }   else if(length(ha.ind) > 0) {
            
                 h.rbef <- dat$a.raft[ha.ind]
      
                } else {
      
                 h.rbef <- dat$h.rbef[i]
               }
          }
      
          if(length(aa.ind) > 0 & length(ah.ind) > 0 ) {
               iy <- which.max(c(aa.ind, ah.ind))
               my <- max(aa.ind, ah.ind)
               if(iy == 1) {
                 a.rbef <- dat$a.raft[my]
           
               } else {
                 a.rbef <- dat$h.raft[my]
           
               }
      
          } else {
      
            if(length(aa.ind) > 0) {
      
               a.rbef <- dat$a.raft[aa.ind]
      
                }   else if(length(ah.ind) > 0) {
      
                 a.rbef <- dat$h.raft[ah.ind]
      
                } else {
      
                 a.rbef <- dat$a.rbef[i]
             }
             }
      
      
      
      
    
        }    
    
    
           tmp <- up.rat(dat$H.pts[i], dat$A.pts[i], h.rbef, a.rbef)
            dat[i, c("h.rbef", "a.rbef", "h.raft", "a.raft")] <- tmp
       }
       return(dat)


}



-测试

out <- f1(data, 1500)

-输出

out
#   ID H.team A.team H.pts A.pts   h.rbef   a.rbef   h.raft   a.raft
#1   1     GS    MIL    94    84 1500.000 1500.000 1508.487 1491.513
#2   2    LAC    CHA   120   107 1500.000 1500.000 1510.021 1489.979
#3   3    MIL    TOR    91    99 1491.513 1500.000 1481.066 1510.447
#4   4    CHA    ATL    84    75 1489.979 1500.000 1498.279 1491.700
#5   5    MIL     GS    88    90 1481.066 1508.487 1475.842 1513.711
#6   6    ATL    MIL    96   105 1491.700 1475.842 1479.614 1487.928
#7   7    TOR    LAC    93    87 1510.447 1510.021 1516.760 1503.708
#8   8    CHA     GS    95    99 1498.279 1513.711 1491.164 1520.826
#9   9    LAC    TOR   113    94 1503.708 1516.760 1517.357 1503.111
#10 10     GS    ATL    85    87 1520.826 1479.614 1514.361 1486.079
#11 11    TOR    CHA   101    92 1503.111 1491.164 1510.678 1483.597
#12 12    MIL    LAC   116   106 1487.928 1517.357 1497.501 1507.783
#13 13    ATL     GS    86    84 1486.079 1514.361 1490.516 1509.924
#14 14    CHA    MIL   102    89 1483.597 1497.501 1494.214 1486.885
#15 15    TOR    ATL    90    89 1510.678 1490.516 1513.710 1487.484

关于r - 如何按顺序更新评级?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67767322/

相关文章:

javascript - 塞萨尔解密。如何处理非字母数字字符 | JS

R 在 data.table 中创建嵌套滚动列表

r - 用 mclapply 控制种子

r - 在R中创建报告

r - 在 r 中使用 for/nested 循环创建新列

r - Phyloseq ggplot2 对象不允许添加某些元素

python - 高效的双for循环

R : How to use apply in this case to speed up the function?

R ggplot : How can I create conditional labeling for a continuous axis ticks

r - 文本挖掘 pdf 文件/词频问题