判断一个值是否连续重复n次

Determining whether a value has been consecutively duplicated n times

我目前正在处理具有如下结构的数据

ID Year1 Year2 Year3 Year4 Year5 Year6
1 2002 2002 2002 2002 2002 NA
2 2002 NA 1001 1001 9999 9999
3 2002 NA 1001 1001 1001 NA
4 3003 3003 3003 NA NA NA
5 1001 1001 1001 1001 NA NA
6 9999 9999 9999 1001 9999 9999
df <- data.frame(ID = c(1, 2, 3, 4, 5, 6),
                 Year1 = c(2002, 2002, 2002, 3003,  1001, 9999),
                 Year2 = c(2002,   NA,   NA, 3003,  1001, 9999),
                 Year3 = c(2002, 1001, 1001, 3003,  1001, 9999),
                 Year4 = c(2002, 1001, 1001,   NA,  1001, 1001),
                 Year5 = c(2002, 9999, 1001,   NA,    NA, 9999),
                 Year6 = c(NA,   9999,   NA,   NA,    NA, 9999))

我的目标是构建一个附加变量 duplicated_from_end,它指示对于每个观察值,最近的非缺失值(即具有最高年份的非缺失值)是否已在至少 n 次(例如,在这个例子中 n = 3 )。例如,对于 ID = 1 的观察,最近的非缺失值是 Year5 中的 2002 年,它(以年为单位倒退)在 Year4 和 [=15= 中连续重复],因此我想要 duplicated = TRUE。总体所需行为如下所述:

ID Year1 Year2 Year3 Year4 Year5 Year6 duplicated_from_end
1 2002 2002 2002 2002 2002 NA TRUE
2 2002 NA 1001 1001 9999 9999 FALSE
3 2002 NA 1001 1001 1001 NA TRUE
4 3003 3003 3003 NA NA NA TRUE
5 1001 1001 1001 1001 NA NA TRUE
6 9999 9999 9999 1001 9999 9999 FALSE

我尝试了 rle() 的解决方案,它可以计算连续的重复项,但我无法确定如何只计算以最新的非缺失变量开头的重复项。任何建议将不胜感激。

考虑按行使用 rle - 循环使用 apply (MARGIN = 1) 的行,对数据应用 run-length-encoding (rle) (没有第一列),从 list 输出中提取 'values' 和相应的 'lengths'。子集不是NA!is.na)的值,并检查最后一个元素(tail)长度是否大于或等于3

df$duplicated_from_end <- apply(df[-1], 1, function(x) {
    rl <- rle(x)
     v1 <- rl$values 
    l1 <- rl$lengths
    i1 <- !is.na(v1)
    tail(l1[i1], 1) >=3 })

-输出

df$duplicated_from_end
[1]  TRUE FALSE  TRUE  TRUE  TRUE FALSE

或者更紧凑的方法是反转列的排列,并使用 rleid

library(data.table)
apply(df[ncol(df):2], 1, \(x) table(rleid(x)[!is.na(x)])[1] >=3)
[1]  TRUE FALSE  TRUE  TRUE  TRUE FALSE