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

Rem*_*i.b 2 search boolean-logic boolean r 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) 
}
Run Code Online (Sandbox Code Playgroud)

测试:

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
Run Code Online (Sandbox Code Playgroud)

然后,我需要一个返回TRUE的函数,如果在给定的列表中布尔向量,则n1至少有一系列由至少两个系列(每侧一个)包裹的TRUE n2.这里的功能:

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)
}
Run Code Online (Sandbox Code Playgroud)

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

测试:

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
Run Code Online (Sandbox Code Playgroud)

现在,信不信由你,我想创建一个函数(fun_3),如果在布尔向量中有一个(至少)至少n1包含在(至少)两个(每边一个)的TRUE之间的系列,则返回TRUE 一系列的n2谬误,其中整个事物(三个系列)被包裹在(至少)两个(每侧一个)系列n3TRUE之间.而且由于我不得不进一步提出这个问题,我在这里请求帮助创建一个函数fun_n,我们在其中输入两个参数TFvec,list_n其中list_nn任何长度的列表.

你能帮我创建这个功能fun_n吗?

Mar*_*gan 6

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

n = length(list_n)
Run Code Online (Sandbox Code Playgroud)

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

r = rle(TFvec); l = r$length
Run Code Online (Sandbox Code Playgroud)

查找可能的起始位置

idx = which(l >= list_n[1] & r$value)
Run Code Online (Sandbox Code Playgroud)

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

idx = idx[idx > n - 1 & idx + n - 1 <= length(l)]
Run Code Online (Sandbox Code Playgroud)

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

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]
}
Run Code Online (Sandbox Code Playgroud)

如果剩下任何值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
}
Run Code Online (Sandbox Code Playgroud)

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

x = sample(c(TRUE, FALSE), 1000000, TRUE)
system.time(runfun(x, rep(2, 5)))
Run Code Online (Sandbox Code Playgroud)

在不到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
}
Run Code Online (Sandbox Code Playgroud)