判断一个值是否连续重复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
我目前正在处理具有如下结构的数据
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