找到一个数字模式R.

时间:2016-05-18 13:50:47

标签: r pattern-matching

我希望找到一个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)

3 个答案:

答案 0 :(得分:1)

1。找到0/1,然后是2s

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))
}

2。仅选择每隔一个位置至少有三个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)找出20之前的所有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)将得到的矢量粘贴到一个字符串中,并使用正则表达式找出所需模式的位置和长度,即交替01等于或大于三次; < / 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