R dplyr подвижная сумма - программирование

R dplyr подвижная сумма

Я выполняю вычисление скользящей суммы через dplyr, но в моей базе данных у меня есть ряд переменных, которые имеют только одно или несколько наблюдений, в результате чего ошибка (k меньше n). Я попытался разрешить это в этом примере с фильтром и слиянием, но задаюсь вопросом, есть ли способ сделать это более элегантно и автоматически в dplyr. см. пример ниже

    #create data
    dg = expand.grid(site = c("Boston","New York"),
                     year = 2000:2004)
    dg$animal="dog"
    dg$animal[10]="cat";dg$animal=as.factor(dg$animal)
    dg$count = rpois(dim(dg)[1], 5) 

Если бы я запускал код ниже, потому что у меня есть только одна строка с "cat", то получается ошибка (ошибка: k <= n не является истиной)

#running average
dg2 = dg %>%
  arrange(site,year,animal) %>%
  group_by(site,animal) %>%
#   filter(animal=="dog") %>%
  mutate(roll_sum = rollsum(x = count, 2, align = "right", fill = NA))

Я попытался решить это, используя следующий код, который отфильтровывает значение "cat" и выполняет последующее слияние, но мне было интересно, можно ли сделать это непосредственно внутри dplyr, тем более, что в этом решении можно было бы указать/знать количество уникальных строк для каждой переменной заранее и вручную отрегулировать, если изменить диапазон текущей суммы и т.д.

dg2 = dg %>%
  arrange(site,year,animal) %>%
  group_by(site,animal) %>%
  filter(animal=="dog") %>%
  mutate(roll_sum = rollsum(x = count, 2, align = "right", fill = NA))

merge(dg,dg2,c("site", "year","animal","count"),all.x=TRUE)

       site year animal count roll_sum
1    Boston 2000    dog     5       NA
2    Boston 2001    dog     6       11
3    Boston 2002    dog     6       12
4    Boston 2003    dog     5       11
5    Boston 2004    dog     3        8
6  New York 2000    dog     8       NA
7  New York 2001    dog     3       11
8  New York 2002    dog    12       15
9  New York 2003    dog     3       15
10 New York 2004    cat     3       NA

Большое спасибо - W

4b9b3361

Ответ 1

Вместо этого вы можете использовать RcppRoll::roll_sum, который возвращает NA, если размер выборки (n) меньше размера окна (k).

set.seed(1)
dg$count = rpois(dim(dg)[1], 5) 
library(RcppRoll)
library(dplyr)
dg %>%
     arrange(site,year,animal) %>%
     group_by(site, animal) %>%
     mutate(roll_sum = roll_sum(count, 2, align = "right", fill = NA))    
#       site year animal count roll_sum
#1    Boston 2000    dog     4       NA
#2    Boston 2001    dog     5        9
#3    Boston 2002    dog     3        8
#4    Boston 2003    dog     9       12
#5    Boston 2004    dog     6       15
#6  New York 2000    dog     4       NA
#7  New York 2001    dog     8       12
#8  New York 2002    dog     8       16
#9  New York 2003    dog     6       14
#10 New York 2004    cat     2       NA

Ответ 2

roll_Sum из RcppRoll вернет NA вместо ошибки, где количество точек данных меньше размера окна.

Однако, если вы хотите вернуть сумму количества присутствующих точек данных, даже если размер окна меньше размера, вы можете использовать функцию rollapplyr из зоопарка.

library(zoo)
library(dplyr)

   dg %>%
         arrange(site,year,animal) %>%
         group_by(site, animal) %>%
         mutate(roll_sum = roll_sum(count, 2, align = "right", fill = NA)) %>%
         mutate(rollapply_sum =rollapplyr(count, 2, sum, partial = TRUE) )

Rollapply_sum вернет исходное значение или сумму имеющихся точек данных, даже если это меньше, чем размер окна вместо возврата NA.

       site  year animal count roll_sum rollapply_sum
     (fctr) (int) (fctr) (int)    (dbl)         (int)
1    Boston  2000    dog     4       NA             4
2    Boston  2001    dog     5        9             9
3    Boston  2002    dog     3        8             8
4    Boston  2003    dog     9       12            12
5    Boston  2004    dog     6       15            15
6  New York  2000    dog     4       NA             4
7  New York  2001    dog     8       12            12
8  New York  2002    dog     8       16            16
9  New York  2003    dog     6       14            14
10 New York  2004    cat     2       NA             2

Ответ 3

 library(dplyr)
 dg %>% 
   arrange(site,year,animal) %>% 
   group_by(site,animal) %>% 
   mutate(rollsum=cumsum(count))