计数观测值时设置固定值

问题描述

目标:创建一个名为“duration”的变量——计算“上个月的值(0或1)”一致的月数,(a) 仅当在给定月份过去至少有 3 次连续观察(b) 算作“0” ' 当上个月的值为 1 时。

例如,数据的样本结构如下所示:

structure(list(group = c(1,1,2,2),month = c(2,4,5,6,7,10,11,12,13,14,15),value= c(NA,NA,1)),class = "data.frame",row.names = c(NA,-17L),codepage = 65001L) 

最终结果看起来像(创建新变量“持续时间”):

╔═══════╦═══════╦═══════╦════════════╦═══════════════════════════════════════════════════════════════════════╗
║ group ║ month ║ value ║ 'duration' ║                              explanation                              ║
╠═══════╬═══════╬═══════╬════════════╬═══════════════════════════════════════════════════════════════════════╣
║   1   ║   2   ║   na  ║     na     ║                                                                       ║
╠═══════╬═══════╬═══════╬════════════╬═══════════════════════════════════════════════════════════════════════╣
║   1   ║   4   ║   0   ║     na     ║ There is no consecutive month in the past for this month              ║
╠═══════╬═══════╬═══════╬════════════╬═══════════════════════════════════════════════════════════════════════╣
║   1   ║   5   ║   1   ║     na     ║ There is only 1 consecutive month in the past (4) for this month      ║
╠═══════╬═══════╬═══════╬════════════╬═══════════════════════════════════════════════════════════════════════╣
║   1   ║   6   ║   1   ║     na     ║ There are only 2 consecutive months in the past (5,6) for this month ║
╠═══════╬═══════╬═══════╬════════════╬═══════════════════════════════════════════════════════════════════════╣
║   1   ║   7   ║   0   ║      0     ║ The prevIoUs month's value is 1,so the duration becomes 0            ║
╠═══════╬═══════╬═══════╬════════════╬═══════════════════════════════════════════════════════════════════════╣
║   1   ║   10  ║   0   ║     na     ║ There is no consecutive month in the past for this month              ║
╠═══════╬═══════╬═══════╬════════════╬═══════════════════════════════════════════════════════════════════════╣
║   1   ║   11  ║   0   ║     na     ║ There is only 1 consecutive month in the past (10) for this month     ║
╠═══════╬═══════╬═══════╬════════════╬═══════════════════════════════════════════════════════════════════════╣
║   1   ║   12  ║   0   ║     na     ║ There is only 2 consecutive months in the past (10,11)               ║
╠═══════╬═══════╬═══════╬════════════╬═══════════════════════════════════════════════════════════════════════╣
║   1   ║   13  ║   0   ║      3     ║ The prevIoUs month's (month 12) value (0) is consistent for 3 months  ║
╠═══════╬═══════╬═══════╬════════════╬═══════════════════════════════════════════════════════════════════════╣
║   1   ║   14  ║   0   ║      4     ║ The prevIoUs month's (month 13) value (0) is consistent for 4 months  ║
╠═══════╬═══════╬═══════╬════════════╬═══════════════════════════════════════════════════════════════════════╣
║   2   ║   7   ║   na  ║     na     ║                                                                       ║
╠═══════╬═══════╬═══════╬════════════╬═══════════════════════════════════════════════════════════════════════╣
║   2   ║   10  ║   1   ║     na     ║ There is no consecutive month in the past                             ║
╠═══════╬═══════╬═══════╬════════════╬═══════════════════════════════════════════════════════════════════════╣
║   2   ║   11  ║   1   ║     na     ║ There is only 1 consecutive month in the past                         ║
╠═══════╬═══════╬═══════╬════════════╬═══════════════════════════════════════════════════════════════════════╣
║   2   ║   12  ║   0   ║     na     ║ There is only 2 consecutive months in the past                        ║
╠═══════╬═══════╬═══════╬════════════╬═══════════════════════════════════════════════════════════════════════╣
║   2   ║   13  ║   0   ║      1     ║ The prevIoUs month's (month 12) value (0) is consistent for 1 month   ║
╠═══════╬═══════╬═══════╬════════════╬═══════════════════════════════════════════════════════════════════════╣
║   2   ║   14  ║   0   ║      2     ║ The prevIoUs month's (month 13) value (0) is consistent for 2 months  ║
╠═══════╬═══════╬═══════╬════════════╬═══════════════════════════════════════════════════════════════════════╣
║   2   ║   15  ║   1   ║      3     ║ The prevIoUs month's (month 14) value (0) is consistent for 3 months  ║
╚═══════╩═══════╩═══════╩════════════╩═══════════════════════════════════════════════════════════════════════╝

我尝试申请的是(由@Will 提供):

setDT(sample)
sample[,month_consecutive := NA]
sample[,value_stable_rows := unlist(lapply(sample[,rle(value),by = group]$length,seq))]
sample[,month_consecutive := unlist(lapply(sample[,rle(diffinv(diff(month) != 1)),by = group]$lengths,value_stable_rows := shift(value_stable_rows,type = "lag"),by = group]
sample[,month_consecutive := shift(month_consecutive,by = group]

sample[,duration := ifelse(value_stable_rows < month_consecutive,value_stable_rows,month_consecutive)]
sample[,month_lag1 := shift(month,n = 1)]
sample[,month_lag2 := shift(month,n = 2)]
sample[,month_lag3 := shift(month,n = 3)]
sample[!((month - month_lag1 == 1) & (month_lag1 - month_lag2 == 1) & (month_lag2 - month_lag3 == 1)),duration := NA]
sample[,.(group,month,value,duration )]

以上代码符合“目标(a)”,但不符合“目标(b)”。我想请教您关于在上个月的值为 1 时可以添加什么来操作计数为“0”的建议。

解决方法

对于第二种情况,在 i 中指定逻辑表达式,即检查 'duration' 中有非 NA 且前一个 'value' (shift) 为 1 的行,然后将“持续时间”分配给 0

out <- sample[,.(group,month,value,duration )]
out[!is.na(duration) & shift(value) == 1,duration := 0]

-输出

out
#    group month value duration
# 1:     1     2    NA       NA
# 2:     1     4     0       NA
# 3:     1     5     1       NA
# 4:     1     6     1       NA
# 5:     1     7     0        0
# 6:     1    10     0       NA
# 7:     1    11     0       NA
# 8:     1    12     0       NA
# 9:     1    13     0        3
#10:     1    14     0        4
#11:     2     7    NA       NA
#12:     2    10     1       NA
#13:     2    11     1       NA
#14:     2    12     0       NA
#15:     2    13     0        1
#16:     2    14     0        2
#17:     2    15     1        3