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

Create sequential counter that restarts on a condition within panel data groups

我有一个面板数据集,我想为其创建一个计数器,该计数器随着面板中的每一步而增加,但只要出现某些情况就会重新启动。就我而言,我使用的是国家/地区年份数据,并想计算事件之间经过的年数。这是一个玩具数据集,其中包含我的真实数据集的主要特征:

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)

我想要做的是在每个国家/地区的观察系列中创建一个针对 df$event 的计数器。当我们开始观察每个国家时,时钟从 1 开始;每年增加1;每当 df$event==1 时它从 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

我尝试使用 splitstackshape 中的 getanID 以及 ififelse 的一些变体,但到目前为止未能获得所需的结果。

我已经在我需要执行此操作的脚本中使用了 dplyr,因此我更喜欢使用它或基础 R 的解决方案,但我将不胜感激。我的数据集不是很大,所以速度不是关键,但效率总是加分项。

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

或使用data.table:

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

编辑:group_by(country, idx = cumsum(event == 1L)) 用于按国家/地区分组和新的分组索引 "idx"。 event == 1L 部分创建了一个逻辑索引,告诉我们列 "event" 是否为整数 1 (TRUE/FALSE)。然后,cumsum(...) 从前 2 行的 0 开始求和,接下来的 3 行从 1 开始,接下来的 3 行从 2 开始,依此类推。我们使用这个新列(+ 国家/地区)根据需要对数据进行分组。 dplyr代码中去掉最后一个to pipe-parts可以查看。

library(splitstackshape)
df$counter <- getanID(cbind(df$country, cumsum(df$event)))[,.id]

我们利用了您的事件列中已有零和一这一事实。这使得索引更容易。我将国家/地区列与 cumsum(df$event) 组合在一起。当该命令本身是 运行 时,您可以看到它的效果:

cumsum(df$event)
 [1] 0 0 1 1 1 2 2 2 3 3

它只会随着每个 1 值的增加而增加。当与国家相结合时,我们能够看到按国家分组的增长。

从那里,我们可以创建一个 id 列。 @AnandaMahto 的 splitstackshape 包具有 getanID 的功能。

 df
   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