Как рассчитать скользящее среднее для нескольких столбцов одновременно с помощью groupby и выбрать в dplyr, игнорируя при этом столбцы groupby

Я пытаюсь получить скользящие средние для многих столбцов одновременно, но у меня возникают трудности, потому что мои группирующие переменные не являются числовыми.

Если бы я выполнял скользящее среднее для одного столбца за раз, мой код выглядел бы примерно так:

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, но приводит к тому, что оператор 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)))

Спасибо.


person Arian Modarres    schedule 04.02.2020    source источник
comment
Возможно, вы ищете mutate_if или mutate_at? (Также я бы рекомендовал использовать больше пробелов и отступов в вашем коде, чтобы он оставался читабельным.)   -  person Axeman    schedule 04.02.2020


Ответы (1)


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
person G. Grothendieck    schedule 04.02.2020