找到包含在两个`n2` FALSE之间的`n1` TRUE,整个事物包含在`n3` TRUE之间,等等

时间:2015-02-27 03:07:09

标签: r search boolean boolean-logic boolean-operations

从一系列TRUE和falses中,我想创建一个返回TRUE的函数,无论序列中某处是否有一系列至少n1个TRUE。这是函数:

fun_1 = function(TFvec, n1){
    nbT = 0
    solution = -1
    for (i in 1:length(x)){
            if (x[i]){
            nbT = nbT + 1
               if (nbT == n1){
                return(T)
                break
               }
            } else {
                nbT = 0
            }
        }
        return (F) 
}

测试:

x = c(T,F,T,T,F,F,T,T,T,F,F,T,F,F)
fun_1(x,3) # TRUE
fun_1(x,4) # FALSE

然后,如果在给定的列表布尔向量中,我需要一个返回TRUE的函数,至少有两个系列(每边一个)包含一系列至少n1个TRUE {{1}愚蠢这里的功能是:

n2

虽然它可能不是一个非常有效的功能!我没有测试过100次,但看起来效果很好!

测试:

fun_2 = function(TFvec, n1, n2){
    if (n2 == 0){
        fun_1(TFvec, n2)        
    }
    nbFB = 0
    nbFA = 0
    nbT = 0
    solution = -1
    last = F
    for (i in 1:length(TFvec)){
        if(TFvec[i]){           
            nbT = nbT + 1
            if (nbT == n1 & nbFB >= n2){
                solution = i-n1+1
            }
            last = T
        } else {
            if (last){
                nbFB = 0
                nbFA = 0        
            }
            nbFB = nbFB + 1
            nbFA = nbFA + 1
            nbT = 0
            if (nbFA == n2 & solution!=-1){
                return(T)
            }
            last = F
        }
    }
    return(F)
}

现在,不管你信不信,我想创建一个函数(x = c(T,F,T,T,F,F,T,T,T,F,F,T,F,F) fun_2(x, 3, 2) # TRUE fun_2(x, 3, 3) # FALSE ),如果在布尔向量中有一个(至少)至少fun_3个TRUE系列,则返回TRUE包裹在(至少)两个(每侧一个)系列n1 falses之间,其中整个事物(三个系列)被包裹在(至少)两个(每侧一个)系列{{{ 1}}真实。由于我不得不进一步提出这个问题,我在这里请求帮助创建一个函数n2,我在其中输入两个参数n3fun_n其中{{1} }}是任意长度的TFvec列表。

你能帮我创建一个函数list_n吗?

2 个答案:

答案 0 :(得分:6)

为方便起见,记录阈值数量的长度

n = length(list_n)

将TRUE和FALSE的向量表示为行程编码,为方便起见记住每次运行的长度

r = rle(TFvec); l = r$length

查找可能的起始位置

idx = which(l >= list_n[1] & r$value)

确保起始位置足够嵌入以满足所有测试

idx = idx[idx > n - 1 & idx + n - 1 <= length(l)]

然后检查连续远程运行的长度是否与条件一致,仅保留

的起点
for (i in seq_len(n - 1)) {
    if (length(idx) == 0)
        break     # no solution
    thresh = list_n[i + 1]
    test = (l[idx + i] >= thresh) & (l[idx - i] >= thresh)
    idx = idx[test]
}

如果idx中还有任何值,则这些是满足条件的rle的索引;初始向量中的起点是cumsum(l)[idx - 1] + 1

组合:

runfun = function(TFvec, list_n) {
    ## setup
    n = length(list_n)
    r = rle(TFvec); l = r$length

    ## initial condition
    idx = which(l >= list_n[1] & r$value)
    idx = idx[idx > n - 1 & idx + n - 1 <= length(l)]

    ## adjacent conditions
    for (i in seq_len(n - 1)) {
        if (length(idx) == 0)
            break     # no solution
        thresh = list_n[i + 1]
        test = (l[idx + i] >= thresh) & (l[idx - i] >= thresh)
        idx = idx[test]
    }

    ## starts = cumsum(l)[idx - 1] + 1
    ## any luck?
    length(idx) != 0
}

这很快,允许运行&gt; =阈值,如问题中所规定的;例如

x = sample(c(TRUE, FALSE), 1000000, TRUE)
system.time(runfun(x, rep(2, 5)))

在不到1/5秒内完成。

有趣的概括允许灵活的条件,例如,精确list_n的运行,如rollapply解决方案

runfun = function(TFvec, list_n, cond=`>=`) {
    ## setup
    n = length(list_n)
    r = rle(TFvec); l = r$length

    ## initial condition
    idx = which(cond(l, list_n[1]) & r$value)
    idx = idx[idx > n - 1 & idx + n - 1 <= length(l)]

    ## adjacent conditions
    for (i in seq_len(n - 1)) {
        if (length(idx) == 0)
            break     # no solution
        thresh = list_n[i + 1]
        test = cond(l[idx + i], thresh) & cond(l[idx - i], thresh)
        idx = idx[test]
    }

    ## starts = cumsum(l)[idx - 1] + 1
    ## any luck?
    length(idx) != 0
}

答案 1 :(得分:4)

创建一个0和1的tpl模板,将其转换为正则表达式模式pat。将x转换为单个字符串0和1,并使用greplpat与其匹配。没有包使用。

fun_n <- function(x, lens) {
  n <- length(lens)
  reps <- c(rev(lens), lens[-1])
  TF <- if (n == 1) 1 else if (n %% 2) 1:0 else 0:1
  tpl <- paste0(rep(TF, length = n), "{", reps, ",}")
  pat <- paste(tpl, collapse = "")
  grepl(pat, paste(x + 0, collapse = ""))
}

# test
x <- c(F, T, T, F, F, T, T, T, F, F, T, T, T, F)
fun_n(x, 3:1)
## TRUE
fun_n(x, 1:3)
## FALSE
fun_n(x, 100)
## FALSE
fun_n(x, 3)
## TRUE
fun_n(c(F, T, F), c(1, 1))
## [1] TRUE
fun_n(c(F, T, T, F), c(1, 1)) 
## [1] TRUE

在下面的示例中,运行时间没有runfun那么快,但是在我的笔记本电脑上运行时间超过2秒的示例仍然非常快。此外,代码的长度相对较短且无环路。

> library(rbenchmark)
> benchmark(runfun(x, 1:3), fun_n(x, 1:3), replications = 10000)[1:4]

            test replications elapsed relative
2  fun_n(x, 1:3)        10000    2.29    1.205
1 runfun(x, 1:3)        10000    1.90    1.000