如何在 R 中的不平衡面板数据中创建自上次事件以来的时间?
How to create time since last event in unbalance panel data in R?
我有不平衡的面板数据,其中有一个二进制变量指示事件是否发生。我想控制时间依赖性,所以我想创建一个变量来指示自上次事件以来已经过去的年数。数据按 dyad-year 组织。
这是一个可重现的示例,其中包含我要实现的目标的向量。谢谢!
id year onset time_since_event
1 1 1989 0 1
2 1 1990 0 2
3 1 1991 1 0
4 1 1992 0 1
5 1 1993 0 2
6 2 1989 0 1
7 2 1990 1 0
8 2 1991 0 1
9 2 1992 1 0
10 3 1991 0 1
11 3 1992 0 2
˚
id <- c(1,1,1,1,1,2,2,2,2,3,3)
year <- c(1989,1990,1991,1992,1993,1989,1990,1991,1992,1991,1992)
onset <- c(0,0,1,0,0,0,1,0,1,0,0)
time_since_event<-c(1,2,0,1,2,1,0,1,0,1,2) #what I want to create
df <- data.frame(cbind(id, year, onset,time_since_event))
我们可以使用data.table
。将 'data.frame' 转换为 'data.table'(setDT(df)
,基于 'onset' 列创建一个 运行 长度的 id 分组变量('ind')使用 rleid
。按 'ind' 和 'id' 列分组,我们将 'time_since_event' 列指定为 'onset' 不等于 1 的行序列。在下一步中,将 'NA' 元素替换为 0.
library(data.table)#v1.9.6+
setDT(df)[, ind:=rleid(onset)][onset!=1, time_since_event:=1:.N ,
by = .(ind, id)][is.na(time_since_event), time_since_event:= 0]
df
# id year onset ind time_since_event
# 1: 1 1989 0 1 1
# 2: 1 1990 0 1 2
# 3: 1 1991 1 2 0
# 4: 1 1992 0 3 1
# 5: 1 1993 0 3 2
# 6: 2 1989 0 3 1
# 7: 2 1990 1 4 0
# 8: 2 1991 0 5 1
# 9: 2 1992 1 6 0
#10: 3 1991 0 7 1
#11: 3 1992 0 7 2
或者可以做得紧凑。按 rleid(onset)
和 'id' 列分组,我们对 'onset' 求反(因此 0 变为 TRUE,1 变为 FALSE),乘以行序列 (1:.N
) 并赋值 (:=
) 它作为 'time_since_event' 列。
setDT(df)[,time_since_event := 1:.N *!onset, by = .(rleid(onset), id)]
df
# id year onset time_since_event
# 1: 1 1989 0 1
# 2: 1 1990 0 2
# 3: 1 1991 1 0
# 4: 1 1992 0 1
# 5: 1 1993 0 2
# 6: 2 1989 0 1
# 7: 2 1990 1 0
# 8: 2 1991 0 1
# 9: 2 1992 1 0
#10: 3 1991 0 1
#11: 3 1992 0 2
或者我们可以使用dplyr
。我们按 'id' 分组并创建另一个变量(通过取 'onset' 中相邻元素的差异(diff
),创建逻辑索引(!=0
)和 cumsum
索引)。在 mutate
中,我们将行序列 (row_number()
) 与取反的 'onset' 相乘(就像之前一样),并使用 select
删除 'ind' 列。
library(dplyr)
df %>%
group_by(id, ind= cumsum(c(TRUE, diff(onset)!=0))) %>%
mutate(time_since_event= (!onset) *row_number()) %>%
ungroup() %>%
select(-ind)
# id year onset time_since_event
# (dbl) (dbl) (dbl) (int)
#1 1 1989 0 1
#2 1 1990 0 2
#3 1 1991 1 0
#4 1 1992 0 1
#5 1 1993 0 2
#6 2 1989 0 1
#7 2 1990 1 0
#8 2 1991 0 1
#9 2 1992 1 0
#10 3 1991 0 1
#11 3 1992 0 2
数据
df <- data.frame(id, year, onset)
我有不平衡的面板数据,其中有一个二进制变量指示事件是否发生。我想控制时间依赖性,所以我想创建一个变量来指示自上次事件以来已经过去的年数。数据按 dyad-year 组织。
这是一个可重现的示例,其中包含我要实现的目标的向量。谢谢!
id year onset time_since_event
1 1 1989 0 1
2 1 1990 0 2
3 1 1991 1 0
4 1 1992 0 1
5 1 1993 0 2
6 2 1989 0 1
7 2 1990 1 0
8 2 1991 0 1
9 2 1992 1 0
10 3 1991 0 1
11 3 1992 0 2
˚
id <- c(1,1,1,1,1,2,2,2,2,3,3)
year <- c(1989,1990,1991,1992,1993,1989,1990,1991,1992,1991,1992)
onset <- c(0,0,1,0,0,0,1,0,1,0,0)
time_since_event<-c(1,2,0,1,2,1,0,1,0,1,2) #what I want to create
df <- data.frame(cbind(id, year, onset,time_since_event))
我们可以使用data.table
。将 'data.frame' 转换为 'data.table'(setDT(df)
,基于 'onset' 列创建一个 运行 长度的 id 分组变量('ind')使用 rleid
。按 'ind' 和 'id' 列分组,我们将 'time_since_event' 列指定为 'onset' 不等于 1 的行序列。在下一步中,将 'NA' 元素替换为 0.
library(data.table)#v1.9.6+
setDT(df)[, ind:=rleid(onset)][onset!=1, time_since_event:=1:.N ,
by = .(ind, id)][is.na(time_since_event), time_since_event:= 0]
df
# id year onset ind time_since_event
# 1: 1 1989 0 1 1
# 2: 1 1990 0 1 2
# 3: 1 1991 1 2 0
# 4: 1 1992 0 3 1
# 5: 1 1993 0 3 2
# 6: 2 1989 0 3 1
# 7: 2 1990 1 4 0
# 8: 2 1991 0 5 1
# 9: 2 1992 1 6 0
#10: 3 1991 0 7 1
#11: 3 1992 0 7 2
或者可以做得紧凑。按 rleid(onset)
和 'id' 列分组,我们对 'onset' 求反(因此 0 变为 TRUE,1 变为 FALSE),乘以行序列 (1:.N
) 并赋值 (:=
) 它作为 'time_since_event' 列。
setDT(df)[,time_since_event := 1:.N *!onset, by = .(rleid(onset), id)]
df
# id year onset time_since_event
# 1: 1 1989 0 1
# 2: 1 1990 0 2
# 3: 1 1991 1 0
# 4: 1 1992 0 1
# 5: 1 1993 0 2
# 6: 2 1989 0 1
# 7: 2 1990 1 0
# 8: 2 1991 0 1
# 9: 2 1992 1 0
#10: 3 1991 0 1
#11: 3 1992 0 2
或者我们可以使用dplyr
。我们按 'id' 分组并创建另一个变量(通过取 'onset' 中相邻元素的差异(diff
),创建逻辑索引(!=0
)和 cumsum
索引)。在 mutate
中,我们将行序列 (row_number()
) 与取反的 'onset' 相乘(就像之前一样),并使用 select
删除 'ind' 列。
library(dplyr)
df %>%
group_by(id, ind= cumsum(c(TRUE, diff(onset)!=0))) %>%
mutate(time_since_event= (!onset) *row_number()) %>%
ungroup() %>%
select(-ind)
# id year onset time_since_event
# (dbl) (dbl) (dbl) (int)
#1 1 1989 0 1
#2 1 1990 0 2
#3 1 1991 1 0
#4 1 1992 0 1
#5 1 1993 0 2
#6 2 1989 0 1
#7 2 1990 1 0
#8 2 1991 0 1
#9 2 1992 1 0
#10 3 1991 0 1
#11 3 1992 0 2
数据
df <- data.frame(id, year, onset)