如何矢量化访问R中的邻居向量元素?

问题描述:

我有以下矢量如何矢量化访问R中的邻居向量元素?

v = c(F, F, F, T, F, F, F, F, F, T, F, F, F) 

如何变更V SO是每个V真元前2种元素和下面的2个元素也被设置为TRUE,使用矢量操作?也就是说,该结果应该是:

F, T, T, T, T, T, F, T, T, T, T, T, F 

当然,这可能是与每个V元素循环中完成的,但我想知道是否有可能向量化这种操作。也不同于this question,v中的元素是独立的,我不需要在每个元素上执行计算。这是一个纯粹的索引问题。

类的事情可能是因为矢量,你会得到:

v[unlist(sapply(which(v),function(x) {x + c(-2,-1,1,2)},simplify = FALSE))] <- TRUE 
> v 
[1] FALSE TRUE TRUE TRUE TRUE TRUE FALSE TRUE TRUE TRUE TRUE TRUE FALSE 

但请注意,你没有指定在真正的要素应该发生什么接近的两端你向量。这将需要更多的工作。你也没有说明如果有两个TRUE元素比两个位置距离更近,会发生什么情况。

或者:

v[outer(which(v),c(-2,-1,1,2),"+")] <- TRUE 
> v 
[1] FALSE TRUE TRUE TRUE TRUE TRUE FALSE TRUE TRUE TRUE TRUE TRUE FALSE 

在基本层面,我们在这里做同样的事情,但第二个选项肯定是更紧凑,尽管可能很难理解。

+1

您可以修改它包括那些约束:'v [独特(as.vector(sapply(其中(V),功能(X){如果( x> 2){x + c(-2,-1,1,2)} else {1:(x + 2)}})))] harkmug 2013-04-24 20:06:42

+1

@rmk是的,虽然只处理我认为,左端点。当然,对于另一端可以做类似的事情,但是我想我们想放弃匿名功能,我想。 – joran 2013-04-24 20:09:42

+1

@rmk检查此线程以讨论如何在边缘修剪矢量:http://stackoverflow.com/questions/16220521/how-to-trim-an-r-vector/16222580#16222580 – 2013-04-25 21:08:20

这是另一个尝试。它似乎对你的数据有效,当第一个元素为TRUE时也是如此。

as.logical(rowSums(embed(c(FALSE, FALSE, v, FALSE, FALSE), 5))) 
# [1] FALSE TRUE TRUE TRUE TRUE TRUE FALSE TRUE TRUE TRUE TRUE TRUE FALSE 

# another attempt with beginning and end TRUE 
v = c(T, F, F, F, F, F, T, F, F, F, F, F, T) 
# [1] TRUE TRUE TRUE FALSE TRUE TRUE TRUE TRUE TRUE FALSE TRUE TRUE TRUE 

到@ flodel的想法类似,人们可以在这里创建一个函数为:

rollOR <- function(vec, dir="both", dist=2) { 
    stopifnot(dir %in% c("left", "right", "both")) 
    stopifnot(dist >= 0) 
    stopifnot(is.logical(vec)) 

    cvec <- rep(FALSE, dist) 
    switch(dir, 
     both = { 
      vec <- c(cvec, vec, cvec) 
      dist <- dist * 2 + 1 
     }, 
     left = { 
      vec <- c(vec, cvec) 
      dist <- dist + 1 
     }, 
     right = { 
      vec <- c(cvec, vec) 
      dist <- dist + 1 
     }) 

    as.logical(rowSums(embed(vec, dist))) 
} 
# direction both sides 
rollOR(v, "both", 2) 
# [1] FALSE TRUE TRUE TRUE TRUE TRUE FALSE TRUE TRUE TRUE TRUE TRUE FALSE 

# left alone 
rollOR(v, "left", 2) 
# [1] FALSE TRUE TRUE TRUE FALSE FALSE FALSE TRUE TRUE TRUE FALSE FALSE FALSE 

# right alone 
rollOR(v, "right", 2) 
# [1] FALSE FALSE FALSE TRUE TRUE TRUE FALSE FALSE FALSE TRUE TRUE TRUE FALSE 
+0

+1 - 非常好! – flodel 2013-04-25 02:19:36

迟到了......你应该申请一个卷积过滤。它会比任何事情都快。唯一的困难是在两端都应该预先加入/追加一对FALSE,所以过滤器不会使用NA s进行初始化。这里有一个功能可以帮你:

within.distance <- function(x, d = 2) { 
    xxx <- c(rep(FALSE, d), x, rep(FALSE, d)) 
    yyy <- as.logical(filter(xxx, rep(1, 2*d+1))) 
    head(tail(yyy, -d), -d) 
} 

within.distance(v) 
# [1] FALSE TRUE TRUE TRUE TRUE TRUE FALSE TRUE TRUE TRUE TRUE TRUE FALSE 
+1

很好的使用过滤器。 – 2013-04-25 03:08:53

+0

证明第一个答案并不总是最好的。尼斯。 – joran 2013-04-25 21:33:58

还有另一种方法。创建一组滞后载体,并or在一起:

library(Hmisc) 
library(functional) 
within.distance <- function(x, d=2) { 
    FLag <- function(x, shift) { 
    x <- Lag(x, shift) 
    x[is.na(x)] <- FALSE 
    return(x) 
    } 

    l <- lapply((-d):d, Curry(FLag, x=x)) 
    return(Reduce(`|`, l)) 
}