如何使用 dplyr 中的 groupby 和 select 一次计算多列的滚动平均值,同时忽略 groupby 列
How to calculate rolling mean for multiple columns at once with a groupby and select in dplyr, while ignoring the groupby columns
我试图一次获得多个列的滚动均值,但我 运行 遇到了困难,因为我的分组变量不是数字。
如果我一次对一列进行滚动平均,我的代码应该如下所示:
NHLReg2<-arrange(NHLReg2,season,team,gameId) %>% group_by(season,team)%>% mutate(xGF= rollapply(xGoalsFor, list( seq(21)), sum, partial = TRUE, fill = NA))
我尝试使用 dplyr 来同时处理许多列:
NHLPP3<-arrange(NHLPP2,season,team,gameId) %>%
group_by(season,team)%>%
select(c(1,2,11:112)) %>%
lapply(function(x){ if(class(x) == "numeric"){
rollapply(x, width=list(-seq(21)), FUN=function(x){sum(x,
na.rm=T)},partial = T, fill = NA)
}else{
return(x)
}
})%>% as.data.frame()
这确实解决了rollapply忽略character/grouping变量的问题,但是导致groupby语句没有效果。我在下面留下了一些样本数据,假设 v1 和 v2 是分组变量,v3 和 v4 是计算滚动平均值的感兴趣的列。
v1<-c('a','a','a','a','a','a','a','a','b','b','b','b','b','b','b')
v2<-c('2010','2010','2010','2010','2010','2010','2010','2010','2020','2020','2020','2020','2020','2020','2020')
v3<-c(1,2,3,4,1,4,5,6,13,5,6,13,4,65,8)
v4<-c(6,13,5,6,13,4,65,8,1,2,3,4,1,4,5)
Data<-as.data.frame(t(rbind(v1,v2,v3,v4)))
谢谢。
Data
,如问题中所定义,没有数字列。都是因素。我们修正下面的定义。然后我们使用 mutate_at
将 rollapplyr
应用于非分组列。为了可以使用 Data
,我们将总和滚动到前 3 个值而不是前 21 个值。 mutate_at
行的替代方法是 mutate_if(is.numeric, ~ rollapplyr(...same...))
.
library(dplyr)
library(zoo)
Data <- data.frame(v1, v2, v3, v4) # v1, v2, v3, v4 are from question
Data %>%
group_by(v1, v2) %>%
mutate_at(vars(-group_cols()),
~ rollapplyr(.x, list(-seq(3)), sum, na.rm = FALSE, partial = TRUE, fill = NA)) %>%
ungroup
给予:
# A tibble: 15 x 4
v1 v2 v3 v4
<fct> <fct> <dbl> <dbl>
1 a 2010 NA NA
2 a 2010 1 6
3 a 2010 3 19
4 a 2010 6 24
5 a 2010 9 24
6 a 2010 8 24
7 a 2010 9 23
8 a 2010 10 82
9 b 2020 NA NA
10 b 2020 13 1
11 b 2020 18 3
12 b 2020 24 6
13 b 2020 24 9
14 b 2020 23 8
15 b 2020 82 9
我试图一次获得多个列的滚动均值,但我 运行 遇到了困难,因为我的分组变量不是数字。
如果我一次对一列进行滚动平均,我的代码应该如下所示:
NHLReg2<-arrange(NHLReg2,season,team,gameId) %>% group_by(season,team)%>% mutate(xGF= rollapply(xGoalsFor, list( seq(21)), sum, partial = TRUE, fill = NA))
我尝试使用 dplyr 来同时处理许多列:
NHLPP3<-arrange(NHLPP2,season,team,gameId) %>%
group_by(season,team)%>%
select(c(1,2,11:112)) %>%
lapply(function(x){ if(class(x) == "numeric"){
rollapply(x, width=list(-seq(21)), FUN=function(x){sum(x,
na.rm=T)},partial = T, fill = NA)
}else{
return(x)
}
})%>% as.data.frame()
这确实解决了rollapply忽略character/grouping变量的问题,但是导致groupby语句没有效果。我在下面留下了一些样本数据,假设 v1 和 v2 是分组变量,v3 和 v4 是计算滚动平均值的感兴趣的列。
v1<-c('a','a','a','a','a','a','a','a','b','b','b','b','b','b','b')
v2<-c('2010','2010','2010','2010','2010','2010','2010','2010','2020','2020','2020','2020','2020','2020','2020')
v3<-c(1,2,3,4,1,4,5,6,13,5,6,13,4,65,8)
v4<-c(6,13,5,6,13,4,65,8,1,2,3,4,1,4,5)
Data<-as.data.frame(t(rbind(v1,v2,v3,v4)))
谢谢。
Data
,如问题中所定义,没有数字列。都是因素。我们修正下面的定义。然后我们使用 mutate_at
将 rollapplyr
应用于非分组列。为了可以使用 Data
,我们将总和滚动到前 3 个值而不是前 21 个值。 mutate_at
行的替代方法是 mutate_if(is.numeric, ~ rollapplyr(...same...))
.
library(dplyr)
library(zoo)
Data <- data.frame(v1, v2, v3, v4) # v1, v2, v3, v4 are from question
Data %>%
group_by(v1, v2) %>%
mutate_at(vars(-group_cols()),
~ rollapplyr(.x, list(-seq(3)), sum, na.rm = FALSE, partial = TRUE, fill = NA)) %>%
ungroup
给予:
# A tibble: 15 x 4
v1 v2 v3 v4
<fct> <fct> <dbl> <dbl>
1 a 2010 NA NA
2 a 2010 1 6
3 a 2010 3 19
4 a 2010 6 24
5 a 2010 9 24
6 a 2010 8 24
7 a 2010 9 23
8 a 2010 10 82
9 b 2020 NA NA
10 b 2020 13 1
11 b 2020 18 3
12 b 2020 24 6
13 b 2020 24 9
14 b 2020 23 8
15 b 2020 82 9