【发布时间】:2021-05-05 04:15:32
【问题描述】:
我正在对篮球数据进行分析。这就是我的数据集的样子(一个真正的示例版本):
df<-data.frame(gmID = 1:20,
H.Team = c("CLE", "MIA", "LAL", "PHI", "CLE", "DET", "CHI", "DAL", "UTA", "PHO", "POR", "WAS", "ORL", "CHA", "BOS", "CHI", "ATL", "DAL", "CLE", "WAS"),
A.Team = c("WAS", "BOS", "DAL", "DEN", "IND", "HOU", "SAC", "WAS", "DAL", "CLE", "LAL", "OKC", "DEN", "IND", "MIL", "CLE", "HOU", "MIA", "UTA", "DEN"),
H.PTS = c(94, 120, 91, 84, 88, 96, 93, 95, 113, 85, 116, 86, 102, 90, 88, 86, 102, 104, 88, 111),
A.PTS = c(84, 107, 99, 75, 90, 105, 87, 99, 94, 87, 106, 84, 89, 89, 99, 115, 109, 84, 86, 88),
H.AST = c(22, 25, 24, 18, 18, 21, 21, 26, 24, 16, 19, 27, 24, 18, 22, 23, 23, 27, 23, 25),
A.AST = c(26, 24, 22, 19, 22, 28, 14, 22, 20, 19, 21, 18, 22, 19, 26, 34, 22, 18, 19, 16))
df
gmID H.Team A.Team H.PTS A.PTS H.AST A.AST
1 1 CLE WAS 94 84 22 26
2 2 MIA BOS 120 107 25 24
3 3 LAL DAL 91 99 24 22
4 4 PHI DEN 84 75 18 19
5 5 CLE IND 88 90 18 22
6 6 DET HOU 96 105 21 28
7 7 CHI SAC 93 87 21 14
8 8 DAL WAS 95 99 26 22
9 9 UTA DAL 113 94 24 20
10 10 PHO CLE 85 87 16 19
11 11 POR LAL 116 106 19 21
12 12 WAS OKC 86 84 27 18
13 13 ORL DEN 102 89 24 22
14 14 CHA IND 90 89 18 19
15 15 BOS MIL 88 99 22 26
16 16 CHI CLE 86 115 23 34
17 17 ATL HOU 102 109 23 22
18 18 DAL MIA 104 84 27 18
19 19 CLE UTA 88 86 23 19
20 20 WAS DEN 111 88 25 16
为了简化问题,我从原始数据集中选择了 20 行,只选择了 2 对比赛统计数据,即主队 (H.) 和客队 (A.) 的比赛统计数据、得分 (PTS) 和助攻 (AST)(分别是我的数据中还有 50 对游戏统计数据)。 请注意,行是按日期排序的,因此不需要进行排列。
目标是对比赛结果进行预测(H.Team 获胜时为 1,A.Team 获胜时为 0),但是现在的数据形式是无用的,因为一旦比赛结束就会报告统计数据.
因此,想法是替换数据框的每个值与前n匹配的滚动平均值。我将在我的工作中设置n=7 或n=10,但现在这并不重要,所以为了简化我将设置n=3。
输出应如下所示:
gmID H.Team A.Team H.PTSav A.PTSav H.ASTav A.ASTav
1 1 CLE WAS NA NA NA NA
2 2 MIA BOS NA NA NA NA
3 3 LAL DAL NA NA NA NA
4 4 PHI DEN NA NA NA NA
5 5 CLE IND 94.00000 NA 22.00000 NA
6 6 DET HOU NA NA NA NA
7 7 CHI SAC NA NA NA NA
8 8 DAL WAS 99.00000 84.00000 22.00000 26.00000
9 9 UTA DAL NA 97.00000 NA 24.00000
10 10 PHO CLE NA 91.00000 NA 20.00000
11 11 POR LAL NA 91.00000 NA 24.00000
12 12 WAS OKC 91.50000 NA 24.00000 NA
13 13 ORL DEN NA 75.00000 NA 19.00000
14 14 CHA IND NA 90.00000 NA 22.00000
15 15 BOS MIL 107.00000 NA 24.00000 NA
16 16 CHI CLE 93.00000 89.66667 21.00000 19.66667
17 17 ATL HOU NA 105.00000 NA 28.00000
18 18 DAL MIA 96.00000 120.00000 22.66667 25.00000
19 19 CLE UTA 96.66667 113.00000 23.66667 24.00000
20 20 WAS DEN 89.66667 82.00000 25.00000 20.50000
例如,对于打了 5 场比赛的团队 CLE,平均 PTS 值如下:
gmID avpts
1 1 NA ---> NA
2 5 94.00000 ---> 94/1
3 10 91.00000 ---> (94+88)/2
4 16 89.66667 ---> (94+88+87)/3
5 19 96.66667 ---> (88+87+115)/3
我使用dplyr 尤其是zoo::rollaply 函数来获取上面显示的值,代码如下:
library(dplyr)
library(zoo)
sub<- df %>%
filter(H.Team == "CLE" | A.Team == "CLE") %>%
mutate(avpts = lag(rollapply(ifelse(H.Team == "CLE", H.PTS,A.PTS), width=3, FUN=mean, align="right", fill=NA, partial=1))) %>%
select(gmID,avpts)
sub
我这样做只是为了一个团队和一个变量,但我可以很容易地为mutate() 中指定它的更多变量执行此操作,如下所示:
mutate(avpts = lag(rollapply(ifelse(H.Team == "CLE", H.PTS,A.PTS), width=3, FUN=mean, align="right", fill=NA, partial=1)),
avast = lag(rollapply(ifelse(H.Team == "CLE", H.AST,A.AST), width=3, FUN=mean, align="right", fill=NA, partial=1)))
问题是我应该为其他 50 个变量执行此操作,最重要的是我需要计算所有团队的值,而不仅仅是一个。 此外,我获得了一个具有正确值的列,但我不知道如何将它们替换为“正确”的位置。
我(部分)解决问题的想法是将上面的代码包装在一个函数中,然后使用 apply 系列中的另一个函数来获取所有团队的值,而不使用 for 循环。
我写了以下函数:
avstats<- function(team) {
sub <- df %>%
filter(.data$H.Team == !!team | .data$A.Team == !!team) %>%
mutate(avpts = lag(rollapply(ifelse(H.Team == !!team, .data$H.PTS, .data$A.PTS),3,mean,align="right",fill=NA,partial=1))) %>%
select(.data$gmID, .data$avpts)
}
最后我通过这个小数据集中的团队列表使用了lapply()。
teams <- c("CLE", "MIA", "LAL", "PHI", "DET", "CHI", "DAL", "UTA", "PHO", "POR", "WAS", "ORL", "CHA", "BOS", "ATL", "DEN", "IND", "HOU", "SAC", "OKC","MIL")
lapply(teams,avstats)
这两个功能似乎一切正常。
但我仍然希望得到两个主要问题的回答:
-
如何在不为每个统计数据写一行的情况下获取所有其他变量的值? (即如何获得平均助攻,失误,ecc..)
-
如何将新生成的平均值“组合”并“放在正确的位置”,以使原始数据结构保持不变?
也许我应该修改我的函数 avstats 添加一些参数,然后使用另一个 apply() 函数,例如 mapply(),但我真的不知道该怎么做。
【问题讨论】:
标签: r dplyr apply zoo rollapply