【问题标题】:Function that sums previous N observations对前 N 个观测值求和的函数
【发布时间】:2021-01-25 18:34:51
【问题描述】:

我想找到一种有效的方法来计算每个模拟 ID、球队和赛季组合的球队在前 N 场比赛中获得的分数(不包括当前比赛中的分数)。如果一支球队到目前为止参加的比赛少于 N 场,则该函数应返回 NA。

一个简化的数据集:

match_ID season simulation_ID home_team team match_result team_points
1 2015-2016 1 TRUE Manchester Utd Home win 3
1 2015-2016 2 TRUE Manchester Utd Draw 1
1 2015-2016 3 TRUE Manchester Utd Home win 3
1 2015-2016 1 FALSE Tottenham Home win 0
1 2015-2016 2 FALSE Tottenham Home win 0
1 2015-2016 3 FALSE Tottenham Away win 3
2 2015-2016 1 TRUE Leicester Home win 3
2 2015-2016 2 TRUE Leicester Home win 3
2 2015-2016 3 TRUE Leicester Away win 0
2 2015-2016 1 FALSE Sunderland Draw 1

预期的输出是数据中的一个额外列,称为“accumulated_team_points”,它返回该球队、赛季和模拟 ID 的最后 N 场比赛中的分数。

我似乎无法找到这样做的方法。

【问题讨论】:

  • 请显示预期的输出
  • 我已经编辑了我的问题,这是您的想法吗?
  • Tor97,其目的是展示您认为这样的操作最终应该提供的结果。如果您看到我的回答,我将证明即使在这样一个看似简单的问题中,也有一些选项会产生不同的输出。在关于 SO 的好问题中,通常会发现尝试的代码、示例数据、给定示例数据的预期输出,以及经常出现问题的警告/错误。

标签: r


【解决方案1】:

这里需要两个操作:分组(我将使用dplyr 演示)和滚动窗口求和(我将使用zoo)。

另外,您的数据有点太稀疏,无法通过team, season, simulation_ID 的所有三个进行分组,所以这次我将仅显示按team 分组。对于更大的数据,请将group_by(team) 替换为group_by(team, season, simulation_ID)

library(dplyr)
k <- 3 # window size
dat %>%
  group_by(team) %>%
  mutate(accumulated_team_points = zoo::rollapply(team_points, k, FUN = sum, align = "right", fill = NA)) %>%
  ungroup()
# # A tibble: 10 x 8
#    match_ID season    simulation_ID home_team team           match_result team_points accumulated_team_points
#       <int> <chr>             <int> <lgl>     <chr>          <chr>              <int>                   <int>
#  1        1 2015-2016             1 TRUE      Manchester Utd Home win               3                      NA
#  2        1 2015-2016             2 TRUE      Manchester Utd Draw                   1                      NA
#  3        1 2015-2016             3 TRUE      Manchester Utd Home win               3                       7
#  4        1 2015-2016             1 FALSE     Tottenham      Home win               0                      NA
#  5        1 2015-2016             2 FALSE     Tottenham      Home win               0                      NA
#  6        1 2015-2016             3 FALSE     Tottenham      Away win               3                       3
#  7        2 2015-2016             1 TRUE      Leicester      Home win               3                      NA
#  8        2 2015-2016             2 TRUE      Leicester      Home win               3                      NA
#  9        2 2015-2016             3 TRUE      Leicester      Away win               0                       6
# 10        2 2015-2016             1 FALSE     Sunderland     Draw                   1                      NA     

对于窗口中的第一个 k-1 实例,默认为 NA,这通常是一个合理且可辩护的默认设置。但是,如果您想对部分和进行求和,请将fill=NA 替换为partial=TRUE

dat %>%
  group_by(team) %>%
  mutate(accumulated_team_points = zoo::rollapply(team_points, k, FUN = sum, align = "right", partial = TRUE)) %>%
  ungroup()
# # A tibble: 10 x 8
#    match_ID season    simulation_ID home_team team           match_result team_points accumulated_team_points
#       <int> <chr>             <int> <lgl>     <chr>          <chr>              <int>                   <int>
#  1        1 2015-2016             1 TRUE      Manchester Utd Home win               3                       3
#  2        1 2015-2016             2 TRUE      Manchester Utd Draw                   1                       4
#  3        1 2015-2016             3 TRUE      Manchester Utd Home win               3                       7
#  4        1 2015-2016             1 FALSE     Tottenham      Home win               0                       0
#  5        1 2015-2016             2 FALSE     Tottenham      Home win               0                       0
#  6        1 2015-2016             3 FALSE     Tottenham      Away win               3                       3
#  7        2 2015-2016             1 TRUE      Leicester      Home win               3                       3
#  8        2 2015-2016             2 TRUE      Leicester      Home win               3                       6
#  9        2 2015-2016             3 TRUE      Leicester      Away win               0                       6
# 10        2 2015-2016             1 FALSE     Sunderland     Draw                   1                       1

仅供参考:我假设数据是预购的。


数据

dat <- structure(list(match_ID = c(1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L), season = c("2015-2016", "2015-2016", "2015-2016", "2015-2016", "2015-2016", "2015-2016", "2015-2016", "2015-2016", "2015-2016", "2015-2016"), simulation_ID = c(1L, 2L, 3L, 1L, 2L, 3L, 1L, 2L, 3L, 1L), home_team = c(TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, FALSE), team = c("Manchester Utd", "Manchester Utd", "Manchester Utd", "Tottenham", "Tottenham", "Tottenham", "Leicester", "Leicester", "Leicester", "Sunderland"), match_result = c("Home win", "Draw", "Home win", "Home win", "Home win", "Away win", "Home win", "Home win", "Away win", "Draw"), team_points = c(3L, 1L, 3L, 0L, 0L, 3L, 3L, 3L, 0L, 1L)), class = "data.frame", row.names = c(NA, -10L))

【讨论】:

  • 难以置信,正是我需要的!谢谢你。我会记住“rollapply”。
  • 可以将滚动部分缩短为:zoo::rollsumr(team_points, k, fill = NA)
猜你喜欢
  • 2020-09-10
  • 2018-09-23
  • 1970-01-01
  • 2018-12-07
  • 1970-01-01
  • 2022-08-19
  • 2019-02-19
  • 2022-11-12
  • 1970-01-01
相关资源
最近更新 更多