根据时间序列中的前一行计数填充 count/sum

Fill count/sum based on previous row count over time series

我对每个组(第 2 组)在一段时间内对事件(第 1 组)进行了计数。我希望将第 1 组事件分散到单独的列中,并使用第 2 组和时间戳作为行。每个单元格将包含一段时间内的事件计数(当前日期到前 4 天)。

参见下面的示例,对于第 2 组(I 和 II)中的每一个,我计算了第 1 组中的事件 A 和 L 在 4 天内发生。

dates = as.Date(c("2011-10-09",
   "2011-10-15",
   "2011-10-16", 
   "2011-10-18", 
   "2011-10-21", 
   "2011-10-22", 
   "2011-10-24")) 
group1=c("A",
    "A",
    "A", 
    "A", 
    "L", 
    "L", 
    "A")
group2=c("I",
    "I",
    "I", 
    "I", 
    "I", 
    "I", 
    "II")

df1 <- data.frame(dates, group1, group2) 

使用 dplyr 管道,我设法生成了以下 table(另请参阅

df1 %>%
  group_by(group1, group2) %>%
  mutate(count = sapply(dates
                    , function(x){
                      sum(dates <= x & dates > (x-4))
                      }))


   dates group1 group2 count
  <date> <fctr> <fctr> <int>
1 2011-10-09      A      I     1
2 2011-10-15      A      I     1
3 2011-10-16      A      I     2
4 2011-10-18      A      I     3
5 2011-10-21      L      I     1
6 2011-10-22      L      I     2
7 2011-10-24      A     II     1

最终,我想获得与此类似的 table,在 I 和 II(第 2 组)中,事件 A 和 L 计数根据日期(时间段 = 当前日期 - 4 天)更新.

         dates  group1 group2  count (A)   count (L)
     1 2011-10-09      A      I        1         0
     2 2011-10-15      A      I        1         0
     3 2011-10-16      A      I        2         0
     4 2011-10-18      A      I        3         0
     5 2011-10-21      L      I        0         1
     6 2011-10-22      L      I        0         2
     7 2011-10-24      A      II       1         0

在更大的数据集中,并非第 1 组中的所有事件都出现在每个第 2 组中。 我如何更新这些空单元格,以便 1) 从前一行结转计数或 2) 根据更新的时间戳/时间段更新计数?

谢谢!

虽然您仍然不太清楚您想要什么(请参阅问题评论),但这里有两种可能的方法。

如果您只想将 count 列展开(出于某种原因)并用 0 填充(无论前 4 天是否发生事件)并且仍按group2 细分(即使你只用 group1 标记)并保留事件详细信息(如你问题中的示例),你可以只创建一个包含你想要的标签的列,然后使用spread 创建新列。这个

df1 %>%
  group_by(group1, group2) %>%
  mutate(count = sapply(dates
                        , function(x){
                          sum(dates <= x & dates > (x-4))
                        })) %>%
  ungroup() %>%
  mutate(toSpread = paste0("Count (", group1, ")")) %>%
  spread(toSpread, count, fill = 0)

returns这个:

       dates group1 group2 `Count (A)` `Count (L)`
*     <date> <fctr> <fctr>       <dbl>       <dbl>
1 2011-10-09      A      I           1           0
2 2011-10-15      A      I           1           0
3 2011-10-16      A      I           2           0
4 2011-10-18      A      I           3           0
5 2011-10-21      L      I           0           1
6 2011-10-22      L      I           0           2
7 2011-10-24      A     II           1           0

这与您在问题中显示的输出相匹配。但是,如果您想要在任何一天计算每个 group1 的事件中发生了多少事件,则您需要退后一步。为此,您需要生成一个包含所需日期的新数据框——每组一行。使用 tidyr 中的 complete 很容易获得。然后,您可以检查每个组在前四天发生的事件。

df1 %>%
  select(dates, group1) %>%
  complete(dates, group1) %>%
  mutate(count = sapply(1:n()
                        , function(idx){
                          sum(df1$dates <= dates[idx] &
                                df1$dates > (dates[idx]-4) &
                                df1$group1 == group1[idx])
                        })) %>%
  mutate(group1 = paste0("Count (", group1, ")")) %>%
  spread(group1, count, fill = 0)

returns:

# A tibble: 7 x 3
       dates `Count (A)` `Count (L)`
*     <date>       <dbl>       <dbl>
1 2011-10-09           1           0
2 2011-10-15           1           0
3 2011-10-16           2           0
4 2011-10-18           3           0
5 2011-10-21           1           1
6 2011-10-22           0           2
7 2011-10-24           1           2

请注意,如果您想包括没有事件的日子,您可以通过将要签入的日期传递到 complete 中来实现。例如:

df1 %>%
  select(dates, group1) %>%
  complete(dates = full_seq(dates, 1), group1) %>%
  mutate(count = sapply(1:n()
                        , function(idx){
                          sum(df1$dates <= dates[idx] &
                                df1$dates > (dates[idx]-4) &
                                df1$group1 == group1[idx])
                        })) %>%
  mutate(group1 = paste0("Count (", group1, ")")) %>%
  spread(group1, count, fill = 0)

returns:

        dates `Count (A)` `Count (L)`
 *     <date>       <dbl>       <dbl>
 1 2011-10-09           1           0
 2 2011-10-10           1           0
 3 2011-10-11           1           0
 4 2011-10-12           1           0
 5 2011-10-13           0           0
 6 2011-10-14           0           0
 7 2011-10-15           1           0
 8 2011-10-16           2           0
 9 2011-10-17           2           0
10 2011-10-18           3           0
11 2011-10-19           2           0
12 2011-10-20           1           0
13 2011-10-21           1           1
14 2011-10-22           0           2
15 2011-10-23           0           2
16 2011-10-24           1           2

根据评论,我想我终于理解了目标。首先,如上所述,我首先创建一个 "long" 数据框,其中包含每个日期的每个 group1/group2 对的计数:

fullDateCounts <-
  df1 %>%
  select(dates, group1, group2) %>%
  complete(dates = full_seq(dates, 1), group1, group2) %>%
  mutate(count = sapply(1:n()
                        , function(idx){
                          sum(df1$dates <= dates[idx] &
                                df1$dates > (dates[idx]-4) &
                                df1$group1 == group1[idx] &
                                df1$group2 == group2[idx]
                              )
                        }))

最上面的是:

        dates group1 group2 count
       <date> <fctr> <fctr> <int>
 1 2011-10-09      A      I     1
 2 2011-10-09      A     II     0
 3 2011-10-09      L      I     0
 4 2011-10-09      L     II     0
 5 2011-10-10      A      I     1
 6 2011-10-10      A     II     0
 7 2011-10-10      L      I     0
 8 2011-10-10      L     II     0
 9 2011-10-11      A      I     1
10 2011-10-11      A     II     0
# ... with 54 more rows

从那里开始,如果您真的需要转换为宽格式,您可以为每个 group2(或 group1,如果您切换列名称)一行:

fullDateCounts %>%
  mutate(group1 = paste0("Count (", group1, ")")) %>%
  spread(group1, count, fill = 0)

returns:

        dates group2 `Count (A)` `Count (L)`
 *     <date> <fctr>       <dbl>       <dbl>
 1 2011-10-09      I           1           0
 2 2011-10-09     II           0           0
 3 2011-10-10      I           1           0
 4 2011-10-10     II           0           0
 5 2011-10-11      I           1           0
 6 2011-10-11     II           0           0
 7 2011-10-12      I           1           0
 8 2011-10-12     II           0           0
 9 2011-10-13      I           0           0
10 2011-10-13     II           0           0
# ... with 22 more rows

或者,您可以为每个 group1/group2 对生成一个列:

fullDateCounts %>%
  mutate(toSpread = paste0("Count (", group1, "-", group2, ")")) %>%
  select(-group1, -group2) %>%
  spread(toSpread, count, fill = 0)

returns

        dates `Count (A-I)` `Count (A-II)` `Count (L-I)` `Count (L-II)`
 *     <date>         <dbl>          <dbl>         <dbl>          <dbl>
 1 2011-10-09             1              0             0              0
 2 2011-10-10             1              0             0              0
 3 2011-10-11             1              0             0              0
 4 2011-10-12             1              0             0              0
 5 2011-10-13             0              0             0              0
 6 2011-10-14             0              0             0              0
 7 2011-10-15             1              0             0              0
 8 2011-10-16             2              0             0              0
 9 2011-10-17             2              0             0              0
10 2011-10-18             3              0             0              0
11 2011-10-19             2              0             0              0
12 2011-10-20             1              0             0              0
13 2011-10-21             1              0             1              0
14 2011-10-22             0              0             2              0
15 2011-10-23             0              0             2              0
16 2011-10-24             0              1             2              0