从数字向量中找出长度为k的连续子向量,满足给定条件。

3

I have a numeric vector in R, say

v= c(2,3,5,6,7,6,3,2,3,4,5,7,8,9,6,1,1,2,5,6,7,11,2,3,4)

现在,我必须找出大小为4的所有连续子向量,并满足子向量中的每个元素都大于2,并且所有子向量在无重叠的意义下是不相交的。因此,我的输出将是:
(3,5,6,7),(3,4,5,7),(5,6,7,11)
编辑:其他例子仅为说明目的:for,
v=c(3,3,3,3,1,3,3,3,3,3,3,3,3) 

输出结果如下:

(3,3,3,3), (3,3,3,3),(3,3,3,3).

并且,针对于:

v= c(2,3,5,5,7,6,3,2,3,4,5,7,8,9,6,1,1,2,5,6,7,11,2,3,4) 

输出结果将为:
(3,5,5,7),(3,4,5,7),(5,6,7,11)

第二个输出条件是,如果我们找到任何一个子数组,比如说(v[m], v[m+1], v[m+2], v[m+3]),其中每个元素都大于2,则它将被放入我的输出中,并且下一个子数组只能从v[m+4](如果可能的话)开始。

你已经尝试编写R函数了吗?你得到了什么结果,发生了什么事情? - Rusan Kax
@user3559153,我刚刚更新了代码。希望能有所帮助。 - akrun
@akrun:它正在工作,谢谢。 - rks
3个回答

5
这个解决方案使用 embed() 创建滞后矩阵,然后从该矩阵中提取所需的行:
v <- c(2,3,5,6,7,6,3,2,3,4,5,7,8,9,6,1,1,2,5,6,7,11,2,3,4)

e <- embed(v, 4)
ret <- which(
  apply(e, 1, function(x)all(x > 2)) &
  apply(e, 1, function(x)length(unique(x)) == 4)
)
rows <- ret[c(1, 1 + which(diff(ret) > 4))]

e[rows, 4:1]

     [,1] [,2] [,3] [,4]
[1,]    3    5    6    7
[2,]    3    4    5    7
[3,]    5    6    7   11

谢谢,但我没有理解ret中的唯一性条件。我认为第二个条件有些混淆。第二个条件只是说,如果我们找到任何子数组(例如(v[m],v[m+1],v[m+2],v[m+3])),其中每个元素都大于2,则它将进入我的输出,并且下一个子数组只能从v[m+4]开始(如果可能的话)。例如,对于v=c(3,3,3,3,3,3,3,3,3,3,3,3),输出为:(3,3,3,3), (3,3,3,3),(3,3,3,3)。对于v=c(2,3,5,5,7,6,3,2,3,4,5,7,8,9,6,1,1,2,5,6,7,11,2,3,4),它将是(3,5,5,7),(3,4,5,7),(5,6,7,11)。(上面的代码分别给出了“none”和(5,7,6,3),(3,4,5,7),(5,6,7,11)) - rks
据我所知,我的代码可以处理你的示例数据。如果你的示例数据不足够,那么我建议你修改你的问题并提供更多信息。从这条评论中很难理解你想要什么。 - Andrie
+1,因为你向我展示了另一个函数(embed),这是我之前没有注意到的。 - Carl Witthoft

1

尝试:

  fun1 <- function(vec, n, cond1) {
  lst1 <- lapply(1:(length(vec) - n+1), function(i) {
    x1 <- vec[i:(i + (n-1))]
    if (all(diff(x1) >= 0) & all(x1 > cond1)) 
        x1
   })
   indx <- which(sapply(lst1, length) == n)
  indx2 <- unlist(lapply(split(indx, cumsum(c(TRUE, diff(indx) != 1))), function(x) x[seq(1, 
    length(x), by = n-1)]))
   lst1[indx2]
}


v1 <- c(3,3,3,3,1,3,3,3,3,3,3,3,3)
v2 <- c(2,3,5,5,7,6,3,2,3,4,5,7,8,9,6,1,1,2,5,6,7,11,2,3,4)
v3 <- c(2,3,5,6,7,6,3,2,3,4,5,7,8,9,6,1,1,2,5,6,7,11,2,3,4)

fun1(v1,4,2)
#[[1]]
#[1] 3 3 3 3

#[[2]]
#[1] 3 3 3 3

#[[3]]
#[1] 3 3 3 3

 fun1(v2,4,2)
 #[[1]]
 #[1] 3 5 5 7

#[[2]]
#[1] 3 4 5 7

#[[3]]
#[1]  5  6  7 11

fun1(v3,4,2)
#[[1]]
#[1] 3 5 6 7

#[[2]]
#[1] 3 4 5 7

#[[3]]
#[1]  5  6  7 11

有两个条件:1.子数组的所有元素都应大于2。2.第二个条件简单地意味着,如果我们找到任何大小为4的子向量(v[m],v[m+1],v[m+2],v[m+3]),其中每个元素>2,则它将成为输出的一部分,并且下一个所需的子向量将以元素v[m+4]开头(如果从它开始的下一个3个元素满足条件1)。现在清楚了吗? - rks
@user3559153 我对“连续数字”感到困惑。在第一个例子中,3和5之间有一个空隙,因此其他情况也是一样的。无论如何,对于您提供的示例,我得到了与您展示的结果相同的结果。 - akrun

0

这里是另一个基于rle的想法:

ff = function(x, size, thres)
{
   valid_subsets = sapply(head(seq_along(x), -(size - 1)), 
                          function(i) all(x[i:(i + (size - 1))] > thres))
   r = rle(valid_subsets)

   lapply(unlist(mapply(function(a, b) a + (seq_len(b) - 1) * size, 
                        (cumsum(r$lengths) - r$lengths + 1)[which(r$values)], 
                        (r$lengths[which(r$values)] + size - 1) %/% size)), 
          function(i) x[i:(i + (size - 1))])
}

ff(c(3,3,3,3,1,3,3,3,3,3,3,3,3), 4, 2)
ff(c(2,3,5,6,7,6,3,2,3,4,5,7,8,9,6,1,1,2,5,6,7,11,2,3,4), 4, 2)

在另一个向量上进行测试(我假设这是正确的输出):

set.seed(4); xx = sample(1:10, 20, T)
xx
# [1]  6  1  3  3  9  3  8 10 10  1  8  3  2 10  5  5 10  6 10  8
ff(xx, 4, 2)
#[[1]]
#[1] 3 3 9 3
#
#[[2]]
#[1] 10  5  5 10

除非我漏掉了什么,否则在“xx”(以及其他情况下)其他发布的答案似乎不起作用:

fun1(xx, 4, 2)
#[[1]]
#[1]  3  8 10 10

#e[rows, 4:1]
#[1]  9  3  8 10

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接