我有以下数据集:
df1 <- data.frame(number = c(1,1,0,0,0,0,0,1,1))
在此数据集中,我想创建第二列,该列显示在第一列和第二个滞后等于0且第一个前导等于1时是否存在情况。一个情况,因此将数字1放在发生从0到1的变化的第二列中(如果不是,则等于44。因此,在此输出中,第二列中的所有行都应等于44,但第8行除外)
这是我的代码。在下面的评论中,我将贴上所需结果的照片。
df1$t<-ifelse(df1[,1]==1 & lag(df1[,1]==0,1,default = 44) & lag(df1[,1]==0,2,default = 44)
& lead(df1[,1]==1,1,default = 44)
,1,44)
答案 0 :(得分:0)
尽管OP要求解释为什么他的代码未返回预期结果(由Gregor's comment解决),但我想提出一种替代方法。
如果我理解正确,那么OP希望在df1$number
中找到所有子序列,这些子序列由两个零后跟两个1,即c(0, 0, 1, 1)
组成。然后,在子序列中包含第一个行的行应用1
标记,而所有其他行应将44
作为默认值。
自data.table
的v1.12.0版(于CRAN 13 Jan 2019)开始,shift()
函数可识别负滞后/超前参数。这样,一列就可以移动多个值。满足上述条件的行号由后续的联接操作标识。最后,df1
使用以下行号进行选择性更新:
# use enhanced sample dataset, rows 10 to 21 added
df1 <- data.frame(number = c(1,1,0,0,0,0,0,1,1,0,1,0,1,1,0,0,1,0,0,1,1))
library(data.table)
setDT(df1)[, t := 44] # coerce to data.table, pre-populate result column
# shift and join
idx <- df1[, shift(number, 2:-1)][.(0, 0, 1, 1), on = paste0("V", 1:4), which = TRUE]
df1[idx, t := 1] # selective update
df1
number t 1: 1 44 2: 1 44 3: 0 44 4: 0 44 5: 0 44 6: 0 44 7: 0 44 8: 1 1 9: 1 44 10: 0 44 11: 1 44 12: 0 44 13: 1 44 14: 1 44 15: 0 44 16: 0 44 17: 1 44 18: 0 44 19: 0 44 20: 1 1 21: 1 44 number t
从本质上讲,通过移动并与期望值进行比较,这可以作为OP的方法。但是,OP的方法需要对四个比较和三个移位操作进行编码,而此处的移位是一步完成的,而所有列的比较是同时由第二步的联接操作完成的。
移位操作
df1[, shift(number, 2:-1)]
返回
V1 V2 V3 V4 1: NA NA 1 1 2: NA 1 1 0 3: 1 1 0 0 4: 1 0 0 0 5: 0 0 0 0 6: 0 0 0 0 7: 0 0 0 1 8: 0 0 1 1 9: 0 1 1 0 10: 1 1 0 1 11: 1 0 1 0 12: 0 1 0 1 13: 1 0 1 1 14: 0 1 1 0 15: 1 1 0 0 16: 1 0 0 1 17: 0 0 1 0 18: 0 1 0 0 19: 1 0 0 1 20: 0 0 1 1 21: 0 1 1 NA V1 V2 V3 V4
在随后的加入操作中,
df1[, shift(number, 2:-1)][.(0, 0, 1, 1), on = paste0("V", 1:4), which = TRUE]
which = TRUE
仅要求返回匹配行的索引,
[1] 8 20