基于日期变量的滚动总和

时间:2019-09-05 13:11:43

标签: r

我想根据每个ID的确切日期对过去3个月中变量的所有值求和。某些ID可能有2磅,另一个ID可能有70磅,等等。例如,在4月15日,我想一直追溯到1月16日,并对这个时间间隔内的所有值求和,包括1月16日和4月15日。在这个时间间隔内甚至有两次观察,甚至是70次。

因此,窗口大小从不相同,这意味着我不能使用Zoo包中的rollapply。

这是一个带有预期输出的小示例数据。

df <- structure(list(id = c(1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 3, 
3, 3, 3, 3, 3, 3, 3, 3), date = c("01/01/2015", "01/02/2015", 
"15/02/2015", "01/03/2015", "01/04/2015", "01/01/2015", "01/02/2015", 
"15/02/2015", "20/02/2015", "01/03/2015", "14/03/2015", "01/04/2015", 
"01/01/2015", "10/02/2015", "15/02/2015", "20/02/2015", "25/02/2015", 
"01/03/2015", "10/03/2015", "20/03/2015", "01/04/2015"), value = c(106, 
57, 43, 105, 180, 109, 36, 102, 97, 97, 113, 83, 178, 19, 80, 
167, 40, 5, 30, 124, 8), expected = c(106, 163, 206, 311, 385, 
109, 145, 247, 344, 441, 554, 528, 178, 197, 277, 444, 484, 489, 
519, 643, 473)), row.names = c(NA, -21L), class = c("tbl_df", 
"tbl", "data.frame"))

2 个答案:

答案 0 :(得分:2)

width中的rollapply可以是宽度的向量,我们可以使用findInterval来计算宽度:

library(dplyr)
library(lubridate)
library(zoo)

df %>%
  group_by(id) %>%
  mutate(date = dmy(date), 
         expected2 = rollapplyr(value, 
          width = 1:n() - findInterval(date - months(3), date), 
          FUN = sum, na.rm = TRUE, fill = NA)) %>%
  ungroup

给予:

# A tibble: 21 x 5
      id date       value expected expected2
   <dbl> <date>     <dbl>    <dbl>     <dbl>
 1     1 2015-01-01   106      106       106
 2     1 2015-02-01    57      163       163
 3     1 2015-02-15    43      206       206
 4     1 2015-03-01   105      311       311
 5     1 2015-04-01   180      385       385
 6     2 2015-01-01   109      109       109
 7     2 2015-02-01    36      145       145
 8     2 2015-02-15   102      247       247
 9     2 2015-02-20    97      344       344
10     2 2015-03-01    97      441       441
# ... with 11 more rows

答案 1 :(得分:0)

我们将date转换为实际的date对象group_by id,并为每个date找出组中最后3个日期个月,并从各自的sum中抽取value

library(dplyr)

df %>%
  mutate(date = as.Date(date, "%d/%m/%Y")) %>%
  group_by(id) %>%
  mutate(ans = purrr::map_dbl(date, ~ sum(value[
             date > (. -  months(3)) & date <= .])))


#      id date       value expected   ans
#    <dbl> <date>     <dbl>    <dbl> <dbl>
# 1     1 2015-01-01   106      106   106
# 2     1 2015-02-01    57      163   163
# 3     1 2015-02-15    43      206   206
# 4     1 2015-03-01   105      311   311
# 5     1 2015-04-01   180      385   385
# 6     2 2015-01-01   109      109   109
# 7     2 2015-02-01    36      145   145
# 8     2 2015-02-15   102      247   247
# 9     2 2015-02-20    97      344   344
#10     2 2015-03-01    97      441   441
# … with 11 more rows