R:基于两个shift语句有条件地创建变量

时间:2019-12-30 17:44:20

标签: r data.table

我有一个如下数据集:

id   age    mod  
1    1      1
1    5      0
1    6      1  
1    7      1
1    9      1   
2    3      0
2    4      1

我想先创建该变量,并仅在mod的每个情节的首次出现时为其赋予true值(每个情节在mod == 1时开始)。情节可以定义为mod == 1的一系列(或独立的一天),其中年龄增加1或年龄增加2。换句话说,如果age == 2和mod == 1,则age ==在3和mod == 0且age == 4和mod == 1的情况下,2-4岁仍处于同一系列中,因为它们彼此之间仍相距2天之内。

因此理想情况下,最终数据集应如下所示:

id   age    mod  first
1    1      1    TRUE
1    5      0    FALSE
1    6      1    TRUE
1    7      1    FALSE
1    9      1    FALSE
2    3      0    FALSE
2    4      1    TRUE

我尝试在data.table中使用lag语句,但未成功。

2 个答案:

答案 0 :(得分:0)

简单的条件是mod[i]==1 & mod[i-1]==0。也就是说,如果一行的mod值为1,而上一行的mod值为0,则将其标记为first

这应该有效:

d = read.table(text='id   age    mod  
1    1      1
1    5      0
1    6      1  
1    7      1
1    9      1   
2    3      0
2    4      1', header=T)

d$first[1] = (d$mod[1]==1)
d$first[2:nrow(d)] = (d$mod[2:nrow(d)]==1 & d$mod[1:nrow(d)-1]==0)

答案 1 :(得分:0)

我相信这应该符合您的条件。可能可以在冗长而复杂的单行代码中完成此操作,但我认为为了清晰起见,将其分为多个步骤将达到相同的目的,而不会对性能造成重大影响。

library(data.table)

## Note - I added a couple more sample rows here
DT <- fread("id   age    mod  
1    1      1
1    5      0
1    6      1  
1    7      1
1    9      1   
2    3      0
2    4      1
3    1      1
3    5      0
3    9      1  
3    10     1")


## Create a column to track jumps in age
DT[, agejump := age - shift(age, n = 1L, fill = NA, type = "lag") > 2L, by = .(id)]

## Create a column to define continued sequences
DT[, continued := mod == 1 & shift(mod, n = 1L, fill = NA, type = "lag") == 1L, by = .(id)]

## backfill the first row of NA's for each id for both variables with FALSE
DT[DT[, .I[1], by = .(id)]$V1, c("agejump","continued") := FALSE]

## define first
DT[,first := (mod == 1 & continued == FALSE | mod == 1 & continued == TRUE & agejump == TRUE)]

print(DT)

#     id age mod agejump continued first
#  1:  1   1   1   FALSE     FALSE  TRUE
#  2:  1   5   0    TRUE     FALSE FALSE
#  3:  1   6   1   FALSE     FALSE  TRUE
#  4:  1   7   1   FALSE      TRUE FALSE
#  5:  1   9   1   FALSE      TRUE FALSE
#  6:  2   3   0   FALSE     FALSE FALSE
#  7:  2   4   1   FALSE     FALSE  TRUE
#  8:  3   1   1   FALSE     FALSE  TRUE
#  9:  3   5   0    TRUE     FALSE FALSE
# 10:  3   9   1    TRUE     FALSE  TRUE
# 11:  3  10   1   FALSE      TRUE FALSE