标记NA的序列的开始

时间:2015-09-04 10:38:58

标签: r

这是一个微不足道的问题,但我似乎没有为此找到整洁的解决方案。 (不排除NA的第一个并再次包括它们)。所以我正在寻找一些不需要NA排除的想法。

我想分别用0 and 12标记1序列的开头,并将NA替换为0以及剩余的0和1的序列。

rle功能在这里有用吗?基地R解决方案将受到欢迎。

示例:

x <- c(rep(NA,10),rep(1,5),rep(NA,5),rep(1,10),rep(NA,3),rep(0,7),rep(NA,15),rep(1,9))
r <- c(0,diff(x)); r[r %in% -1] <- 2

从此示例数据:

x
[1] NA NA NA NA NA NA NA NA NA NA  1  1  1  1  1 NA NA NA NA NA  1  1  1  1  1  1  1  1  1  1 NA NA NA  0  0  0  0  0  0  0 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA  1  1  1  1  1  1  1  1  1

期望的输出:

[1] 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0

1 个答案:

答案 0 :(得分:1)

我们可以使用rle创建一个分组变量(&#39; gr&#39;)到split&#39; x&#39;进入list。使用match将第一个元素0或1替换为2或1,使用0连接unlist,然后用0替换NA元素。

xN <- x
xN[is.na(xN)] <- -999
v1 <- rle(xN)$lengths
gr <- rep(seq_along(v1), v1)


x1 <- unlist(lapply(split(x, gr), function(x) 
          c(match(x[1],1:0),rep(0,length(x)-1)) ), use.names=FALSE)
x1[is.na(x1)] <- 0
x1
#[1] 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0
#[39] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0

或者代替split,我们可以使用whichdiff来替换值。

x1 <- (!x)+2*(!is.na(x))-1
ind <- which(!is.na(x))
x1[c(ind[c(FALSE,diff(ind)==1)], which(is.na(x)))] <- 0
x1
#[1] 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0
#[39] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0

或者我们可以使用rleid的devel版本中的data.table作为分组变量。使用match将2和1替换为0和1的第一个元素,并将NA值更改为0.

library(data.table)#v1.9.5+
DT <- setDT(list(x))
DT[, c(match(V1[1], 1:0), rep(0, .N-1)) ,rleid(V1)][is.na(V1), V1:=0]$V1
#[1] 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0
#[39] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0