我想根据每个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"))
答案 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