从一系列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
,我在其中输入两个参数n3
和fun_n
其中{{1} }}是任意长度的TFvec
列表。
你能帮我创建一个函数list_n
吗?
答案 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,并使用grepl
将pat
与其匹配。没有包使用。
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