创建在面板数据组内的条件下重新启动的顺序计数器

ulf*_*der 5 r time-series dplyr

我有一个面板数据集,我想为其创建一个计数器,该计数器随着面板中的每个步骤而增加,但只要发生某些情况就会重新启动.就我而言,我正在使用国家年度数据,并希望计算事件之间的年份.这是一个玩具数据集,其中包含我真实的主要特征:

df <- data.frame(country = rep(c("A","B"), each=5), year=rep(2000:2004, times=2), event=c(0,0,1,0,0,1,0,0,1,0), stringsAsFactors=FALSE)
Run Code Online (Sandbox Code Playgroud)

我想要做的是创建一个df$event在每个国家的一系列观察中都有关键的计数器.当我们开始观察每个国家时,时钟从1开始; 随着每年的过去,它增加1; 并且它会在1时重新启动df$event==1.所需的输出是这样的:

   country year event clock
1        A 2000     0     1
2        A 2001     0     2
3        A 2002     1     1
4        A 2003     0     2
5        A 2004     0     3
6        B 2000     1     1
7        B 2001     0     2
8        B 2002     0     3
9        B 2003     1     1
10       B 2004     0     2
Run Code Online (Sandbox Code Playgroud)

我已经尝试使用getanIDsplitstackshape和一些变化ififelse但到目前为止还没有得到期望的结果.

我已经dplyr在我需要这样做的脚本中使用了,所以我更喜欢使用它或基础R的解决方案,但我会感激任何有用的东西.我的数据集并不大,因此速度并不重要,但效率始终是一个优势.

tal*_*lat 15

有了dplyr这将是:

df %>% 
  group_by(country, idx = cumsum(event == 1L)) %>% 
  mutate(counter = row_number()) %>% 
  ungroup %>% 
  select(-idx)

#Source: local data frame [10 x 4]
#
#   country year event counter
#1        A 2000     0       1
#2        A 2001     0       2
#3        A 2002     1       1
#4        A 2003     0       2
#5        A 2004     0       3
#6        B 2000     1       1
#7        B 2001     0       2
#8        B 2002     0       3
#9        B 2003     1       1
#10       B 2004     0       2
Run Code Online (Sandbox Code Playgroud)

或使用data.table:

library(data.table)
setDT(df)[, counter := seq_len(.N), by = list(country, cumsum(event == 1L))]
Run Code Online (Sandbox Code Playgroud)

编辑:group_by(country, idx = cumsum(event == 1L))用于按国家/地区分组和新的分组索引"idx".该event == 1L部分创建一个逻辑索引,告诉我们"事件"列是否为整数1(TRUE/ FALSE).然后,cumsum(...)总结从前2行的0开始,接下来的3的1,接下来的3的2,依此类推.我们使用此新列(+国家/地区)根据需要对数据进行分组.如果删除dplyr代码中最后一个管道部件,可以检查它.