我希望找到一个0/1后跟一个2的模式,它连续发生三次以上。我想找到这种模式,并将这种模式中的2变换为1 - 例如
输入:
Y <- c(0,1,0,3,2,5,2,1,2,0,2,1,2,0,1,2,1,3,1,2,1)
找到模式的一些函数findPattern:
findPattern(Y)
输出以下内容:
[1] 0 0 0 0 0 0 0 0 1 0 1 0 1 0 0 0 0 0 0 0 0
我尝试了以下内容:
as.numeric(Y == 2 & lead(Y) %in% 1:2)
答案 0 :(得分:1)
findPattern<-function(Y){
as.numeric(Y==2 & (c(NA,Y[-length(Y)])==0 |c(NA,Y[-length(Y)])==1 ))
}
我在开头添加一个NA并删除最后一个项目,以便你移动&#34;您的向量按1个位置但仍保持相同的向量长度。这样就可以避免for
循环。
如果你想使用%in%
来避免第二段:
findPattern<-function(Y){
as.numeric(Y==2 & (c(NA,Y[-length(Y)]) %in% c(0,1))
}
findPattern<-function(Y){
w <- which(Y==2 & (c(NA,Y[-length(Y)]) %in% c(0,1)))
centers<- w[((w - 2) %in% w) & ((w+2) %in% w)]
result<-rep(0, times = length(Y))
result[c(centers,centers-2,centers+2)]<-1
return(result)
}
测试:
findPattern(c(0,1,0,3,2,5,2,1,2,0,2,1,2,0,1,2,1,3,1,2,1))
[1] 0 0 0 0 0 0 0 0 1 0 1 0 1 0 0 0 0 0 0 0 0
答案 1 :(得分:1)
这是一种解决问题的可能方法,您可以将其与正则表达式结合使用以找到模式。
开始矢量:
> Y
[1] 0 2 0 3 2 5 2 1 2 0 2 1 2 0 1
1)找出2
或0
之前的所有1
;
> ind <- as.integer(lag(Y %in% c(0, 1)) & (Y == 2) )
> ind
[1] 0 1 0 0 0 0 0 0 1 0 1 0 1 0 0
2)将得到的矢量粘贴到一个字符串中,并使用正则表达式找出所需模式的位置和长度,即交替0
和1
等于或大于三次; < / p>
> id <- gregexpr("(01){3,}", paste0(ind, collapse = ""))
> id
[[1]]
[1] 8
attr(,"match.length")
[1] 6
attr(,"useBytes")
[1] TRUE
3)从正则表达式结果中提取位置和长度,并将它们转换为索引模式;
> start <- as.numeric(id[[1]])
> end <- start + attr(id[[1]], "match.length") - 1
> indArray <- unlist(Map(`:`, start, end))
> indArray
[1] 8 9 10 11 12 13
4)将01
模式下的所有值分配给3
次,为0
> ind[-indArray] <- 0
> ind
[1] 0 0 0 0 0 0 0 0 1 0 1 0 1 0 0
将它们包装成一个函数:
library(dplyr)
findPattern <- function(Y) {
ind <- as.integer(lag(Y %in% c(0, 1)) & (Y == 2) )
id <- gregexpr("(01){3,}", paste0(ind, collapse = ""))
start <- as.numeric(id[[1]])
end <- start + attr(id[[1]], "match.length") - 1
indArray <- unlist(Map(`:`, start, end))
ind[-indArray] <- 0
ind
}
答案 2 :(得分:0)
使用stringi
包
Y <- c(0,1,0,3,2,5,2,1,2,0,2,1,2,0,1)
matchVec = stri_count(Y,fixed=2)
remapVec = as.integer(matchVec & (cumsum(matchVec)>=3))
remapVec
#[1] 0 0 0 0 0 0 0 0 1 0 1 0 1 0 0