滚动时间窗口的累计和

时间:2014-07-21 14:38:17

标签: r

我通过人员标识符获得包含开始日期和结束日期的法术数据。

temp <- structure(list(id = structure(c(1L, 1L, 1L, 2L, 2L, 2L), .Label = c("1", 
"2"), class = "factor"), spell = c(1L, 2L, 3L, 1L, 2L, 3L), date1 = structure(c(14611, 
14654, 15141, 14853, 14867, 14975), class = "Date"), date2 = structure(c(14612, 
14656, 15142, 14862, 14872, 14976), class = "Date")), class = "data.frame", .Names = c("id", 
"spell", "date1", "date2"), row.names = c(NA, -6L))

我想计算过去一年中法术天数的滚动总数(由365天窗口定义),以便每行获得法术中包含的总天数。 ,一年之内。

所以在我的例子中,人1有3个法术,其中两个发生在一年的窗口内(第1行和第2行)。第一个法术没有先验,因此days.observed.in.past.yr为0.第二个法术有一个先前法术(第1行),长度为1天,所以days.observed.in.past.yr为0。

第2人有三个法术,都在一年内发生。对于法术2,第2个人,之前的法术是9天,所以days.observed.in.past.yr是9.然后对于法术3,有两个先前的法术和天.observed.in.past.yr是14 (9 + 5)。这将继续添加当前行的365天窗口内的多个法术。

id  spell   date1       date2       days.observed.in.past.yr
1     1     2010-01-02 2010-01-03   0
1     2     2010-02-14 2010-02-16   1
1     3     2011-06-16 2011-06-17   0
2     1     2010-09-01 2010-09-10   0
2     2     2010-09-15 2010-09-20   9
2     3     2011-01-01 2011-01-02   14

然而,除了计算一年前的法术长度和日期之类的琐碎事情之外我还不知道该怎么做。我发现的最接近的类似问题是rgolf:rolling window,但我不知道如何将此问题应用到我的问题中。

有人可以帮忙吗?

2 个答案:

答案 0 :(得分:2)

以下是使用dplyr执行该操作的一种方法:

require(dplyr)

temp %>%
  mutate(year1 = format(date1, "%Y"),
         year2 = format(date2, "%Y")) %>%
  group_by(id) %>%
  mutate(count = ifelse(lag(year1, 1, default = 0) == year1, lag(date2, 1) - lag(date1,1), 0 )) %>%
  select(-c(year1, year2))

#Source: local data frame [5 x 4]
#Groups: id
#
#  id      date1      date2 count
#1  1 2010-01-02 2010-01-03     0
#2  1 2010-02-14 2010-02-16     1
#3  1 2011-06-16 2011-06-17     0
#4  2 2010-09-01 2010-09-10     0
#5  2 2010-09-15 2010-09-20     9

在评论后编辑1

使用365天&#34;滚动&#34;窗口,您可以使用以下内容:

temp %>%
  group_by(id) %>%
  mutate(count = ifelse(date1 - lag(date1, 1, default = 0) <= 365, lag(date2, 1) - lag(date1,1), 0))

结果与上面的样本数据相同。

编辑2

我再次考虑了这一点并且怀疑第一次编辑实际上是按预期运行的,因为它只查看前一行以检查该行是否少于当前date1之前365天。所以我提出了另一个版本,它查看每个id的所有行,创建一个365天窗口内的数据组,然后总结日期差异 - 也许这就是你想要的。

df %>%
  group_by(id) %>%
  arrange(id, date1) %>%
  mutate(delta = floor(c(0, diff(date1)) / 365),
         delta = cumsum(delta)) %>%
  group_by(delta, add = TRUE) %>%
  mutate(count = cumsum(as.numeric(date2-date1)) - (date2 - date1)) %>%
  ungroup() %>%
  select(-delta)

我不清楚的问题是,您是否只想总结上一行中的日期差异(如果它存在且不到365天,那么编辑1应该有效)或者你想要总结所有之前不到365天的差异(在这种情况下,编辑2应该有效)。

答案 1 :(得分:0)

使用runner软件包可以实现此目的。 OP需要过去365天的总和,不包括当前观察值。 sum_run在365天内计算date2 - date1的总和。要排除当前行,可以减去- spell_days或使用lag = 1(不包括当前日期)。

library(dplyr)
library(runner)

temp %>%
  group_by(id) %>%
  mutate(

    spell_days = date2 - date1,

    days.observed.in.past.yr = sum_run(
      x = spell_days, 
      k = 365, 
      idx = date1
    ) - spell_days

  )

#   id    spell date1      date2      spell_days days.observed.in.past.yr
#   <fct> <int> <date>     <date>     <drtn>     <drtn>                  
# 1 1         1 2010-01-02 2010-01-03 1 days      0 days                 
# 2 1         2 2010-02-14 2010-02-16 2 days      1 days                 
# 3 1         3 2011-06-16 2011-06-17 1 days      0 days                 
# 4 2         1 2010-09-01 2010-09-10 9 days      0 days                 
# 5 2         2 2010-09-15 2010-09-20 5 days      9 days                 
# 6 2         3 2011-01-01 2011-01-02 1 days     14 days