创建在面板数据组内的条件下重新启动的顺序计数器
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
以及 if
和 ifelse
的一些变体,但到目前为止未能获得所需的结果。
我已经在我需要执行此操作的脚本中使用了 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
我有一个面板数据集,我想为其创建一个计数器,该计数器随着面板中的每一步而增加,但只要出现某些情况就会重新启动。就我而言,我使用的是国家/地区年份数据,并想计算事件之间经过的年数。这是一个玩具数据集,其中包含我的真实数据集的主要特征:
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
以及 if
和 ifelse
的一些变体,但到目前为止未能获得所需的结果。
我已经在我需要执行此操作的脚本中使用了 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