问题描述
我正在对篮球数据进行分析。这就是我的数据集的样子(它的真正示例版本):
df<-data.frame(gmID = 1:20,H.Team = c("CLE","MIA","LAL","PHI","CLE","DET","CHI","DAL","UTA","PHO","POR","WAS","ORL","CHA","BOS","ATL","WAS"),A.Team = c("WAS","DEN","IND","HOU","SAC","OKC","MIL","DEN"),H.PTS = c(94,120,91,84,88,96,93,95,113,85,116,86,102,90,104,111),A.PTS = c(84,107,99,75,105,87,94,106,89,115,109,88),H.AST = c(22,25,24,18,21,26,16,19,27,22,23,25),A.AST = c(26,28,14,20,34,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 行,仅选择了两对由主队 (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",partial=1)),avast = lag(rollapply(ifelse(H.Team == "CLE",H.AST,A.AST),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,partial=1))) %>%
select(.data$gmID,.data$avpts)
}
最后,我通过这个小数据集中的团队列表使用了 lapply()
。
teams <- c("CLE","MIL")
lapply(teams,avstats)
而且这两个函数似乎一切正常。
但是我仍然希望回答两个主要问题:
也许我应该修改我的函数 avstats
添加一些参数并因此使用另一个 apply() 函数,例如 mapply()
,但我真的不知道该怎么做。
解决方法
你想要这个吗? (使用了来自 mean_run
的 library(runner)
)。
- 您可以根据需要为任意数量的变量自动执行此过程。只需在
.cols
的 - 要更改滚动窗口大小,只需根据选择更改
k
中的mean_run
。
mutate(across...
参数中使用他们的名字
df %>% pivot_longer(!gmID,names_to = c("H_T",".value"),names_pattern = "(.+)\\.(.+)") %>%
group_by(Team) %>%
mutate(across(.cols = c(PTS,AST),~ runner::mean_run(x = .,k = 3,lag = 1),.names = '{.col}_av')) %>%
pivot_wider(id_cols = gmID,names_from = H_T,names_glue = "{H_T}_{.value}",values_from = -c(gmID,H_T))
# A tibble: 20 x 11
gmID H_Team A_Team H_PTS A_PTS H_AST A_AST H_PTS_av A_PTS_av H_AST_av A_AST_av
<int> <chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 1 CLE WAS 94 84 22 26 NA NA NA NA
2 2 MIA BOS 120 107 25 24 NA NA NA NA
3 3 LAL DAL 91 99 24 22 NA NA NA NA
4 4 PHI DEN 84 75 18 19 NA NA NA NA
5 5 CLE IND 88 90 18 22 94 NA 22 NA
6 6 DET HOU 96 105 21 28 NA NA NA NA
7 7 CHI SAC 93 87 21 14 NA NA NA NA
8 8 DAL WAS 95 99 26 22 99 84 22 26
9 9 UTA DAL 113 94 24 20 NA 97 NA 24
10 10 PHO CLE 85 87 16 19 NA 91 NA 20
11 11 POR LAL 116 106 19 21 NA 91 NA 24
12 12 WAS OKC 86 84 27 18 91.5 NA 24 NA
13 13 ORL DEN 102 89 24 22 NA 75 NA 19
14 14 CHA IND 90 89 18 19 NA 90 NA 22
15 15 BOS MIL 88 99 22 26 107 NA 24 NA
16 16 CHI CLE 86 115 23 34 93 89.7 21 19.7
17 17 ATL HOU 102 109 23 22 NA 105 NA 28
18 18 DAL MIA 104 84 27 18 96 120 22.7 25
19 19 CLE UTA 88 86 23 19 96.7 113 23.7 24
20 20 WAS DEN 111 88 25 16 89.7 82 25 20.5