我正在尝试创建一种"开关"在我的数据中,当特定事件发生时,二进制指示符将从1切换到0以进行所有下一次观察(按时间排序的数据)。以下是我目前的数据样本。
Time Event ID_1 ID_2 ID_3 ID_4 ID_5
1 0 1 1 1 1 1
2 0 1 1 1 1 1
3 0 1 1 1 1 1
4 0 1 1 1 1 1
5 ID_2 1 1 1 1 1
6 0 1 1 1 1 1
7 ID_3 1 1 1 1 1
8 0 1 1 1 1 1
然后这就是我想要的:
Time Event ID_1 ID_2 ID_3 ID_4 ID_5
1 0 1 1 1 1 1
2 0 1 1 1 1 1
3 0 1 1 1 1 1
4 0 1 1 1 1 1
5 ID_2 1 0 1 1 1
6 0 1 0 1 1 1
7 ID_3 1 0 0 1 1
8 0 1 0 0 1 1
正如您所看到的,当" EVENT"取0以外的值,我希望与EVENT值匹配的变量从1切换到0,并且我希望它保持为0,因为观察继续进行。任何帮助都会很棒。
感谢。
答案 0 :(得分:4)
我会使用library(data.table)
执行此操作,创建事件发生时间的“查找”表,然后使用non-equi
联接更新事件后的值
## extract just the rows where the updates occur
eventRows <- df[df$Event != "0", c("Time", "Event")]
library(data.table)
## set as data.tables
setDT(eventRows)
setDT(df)
## melt into long-form
df_melted <- melt(df, id.vars = c("Time", "Event"))
## perform a non-equi join, and update-by-reference the values
## meeting the criteria
df_melted[
eventRows
, on = .(variable == Event, Time >= Time)
, value := 0
]
## put back into wide form
df_res <- dcast(df_melted, formula = Time + Event ~ variable)
df_res
# Time Event ID_1 ID_2 ID_3 ID_4 ID_5
# 1: 1 0 1 1 1 1 1
# 2: 2 0 1 1 1 1 1
# 3: 3 0 1 1 1 1 1
# 4: 4 0 1 1 1 1 1
# 5: 5 ID_2 1 0 1 1 1
# 6: 6 0 1 0 1 1 1
# 7: 7 ID_3 1 0 0 1 1
# 8: 8 0 1 0 0 1 1
## convert back to a data.frame using
## setDF(df)
df <- read.table(text = "Time Event ID_1 ID_2 ID_3 ID_4 ID_5
1 0 1 1 1 1 1
2 0 1 1 1 1 1
3 0 1 1 1 1 1
4 0 1 1 1 1 1
5 ID_2 1 1 1 1 1
6 0 1 1 1 1 1
7 ID_3 1 1 1 1 1
8 0 1 1 1 1 1", header = T)
答案 1 :(得分:3)
运行cumsum
计数器以查看检测到每个变量的位置,然后覆盖相应的变量:
dat[3:7] <- lapply(names(dat[3:7]), function(x) 1-cumsum(dat$Event==x) )
dat
# Time Event ID_1 ID_2 ID_3 ID_4 ID_5
#1 1 0 1 1 1 1 1
#2 2 0 1 1 1 1 1
#3 3 0 1 1 1 1 1
#4 4 0 1 1 1 1 1
#5 5 ID_2 1 0 1 1 1
#6 6 0 1 0 1 1 1
#7 7 ID_3 1 0 0 1 1
#8 8 0 1 0 0 1 1
此方法不依赖于事先存在的列。
vars <- paste("ID",1:5,sep="_")
dat[vars] <- lapply(vars, function(x) 1-cumsum(dat$Event==x) )