dplyr:使用滚动时间窗口对数据进行分组和汇总/变更

div*_*ero 7 r time-series lubridate dplyr

我有不规则的时间序列数据表示用户的某种类型的交易.每行数据都带有时间戳,表示当时的事务.根据数据的不规则性,一些用户一天可能有100行,而其他用户一天可能有0或1个事务.

数据可能如下所示:

data.frame(
  id = c(1, 1, 1, 1, 1, 2, 2, 3, 4),
  date = c("2015-01-01", 
           "2015-01-01", 
           "2015-01-05", 
           "2015-01-25",
           "2015-02-15",
           "2015-05-05", 
           "2015-01-01", 
           "2015-08-01", 
           "2015-01-01"),
  n_widgets = c(1,2,3,4,4,5,2,4,5)
)

   id       date n_widgets
1  1 2015-01-01         1
2  1 2015-01-01         2
3  1 2015-01-05         3
4  1 2015-01-25         4
5  1 2015-02-15         4
6  2 2015-05-05         5
7  2 2015-01-01         2
8  3 2015-08-01         4
9  4 2015-01-01         5
Run Code Online (Sandbox Code Playgroud)

我经常想知道一些关于用户的滚动统计数据.例如:对于某个特定日期的此用户,过去30天内发生的交易次数,前30天内售出的小部件数量等.

对应上面的例子,数据应如下所示:

   id     date    n_widgets  n_trans_30  total_widgets_30
1  1 2015-01-01         1           1             1
2  1 2015-01-01         2           2             3
3  1 2015-01-05         3           3             6
4  1 2015-01-25         4           4             10
5  1 2015-02-15         4           2             8
6  2 2015-05-05         5           1             5
7  2 2015-01-01         2           1             2
8  3 2015-08-01         4           1             4
9  4 2015-01-01         5           1             5
Run Code Online (Sandbox Code Playgroud)

如果时间窗口是每天,则解决方案很简单: data %>% group_by(id, date) %>% summarize(...)

同样,如果时间窗口是每月,那么使用lubridate也相对简单: data %>% group_by(id, year(date), month(date)) %>% summarize(...)

然而,我遇到的挑战是如何设置任意时间段的时间窗口:5天,10天等.

还有RcppRoll库,但是两者RcppRoll和滚动功能zoo似乎都是常规时间序列的更多设置.据我所知,这些窗口函数基于行数而不是指定的时间段工作 - 关键区别在于某个时间段可能具有不同的行数,具体取决于日期和用户.

例如,对于用户1,前5天的交易数量2015-01-01等于100个交易,而对于同一个用户,前5天的交易数量2015-02-01等于5个交易.因此,回顾一定数量的行将无法正常工作.

此外,还有另一个SO线程讨论不规则时间序列类型数据的滚动日期(根据滚动日期内存在的条件创建新列)但是接受的解决方案正在使用data.table,我正在寻找dplyr实现此目的的方法.

我想这个问题的核心是,这个问题可以通过回答这个问题来解决:我怎样才能group_by在任意时间段内完成dplyr.或者,如果dplyr没有复杂的方法可以实现上述目标group_by,我该怎么办呢?

编辑:更新的示例,使滚动窗口的性质更清晰.

Gop*_*ala 2

根据下面的评论进行编辑。

您最多可以尝试这样的事情 5 天:

df %>%
  arrange(id, date) %>%
  group_by(id) %>%
  filter(as.numeric(difftime(Sys.Date(), date, unit = 'days')) <= 5) %>%
  summarise(n_total_widgets = sum(n_widgets))
Run Code Online (Sandbox Code Playgroud)

在本例中,当前日期后五天内没有任何天。因此,它不会产生任何输出。

要获取每个 ID 的最后五天,您可以执行以下操作:

df %>%
   arrange(id, date) %>%
   group_by(id) %>%
   filter(as.numeric(difftime(max(date), date, unit = 'days')) <= 5) %>%
   summarise(n_total_widgets = sum(n_widgets))
Run Code Online (Sandbox Code Playgroud)

结果输出将是:

Source: local data frame [4 x 2]

     id n_total_widgets
  (dbl)           (dbl)
1     1               4
2     2               5
3     3               4
4     4               5
Run Code Online (Sandbox Code Playgroud)