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

时间:2013-04-24 19:33:56

标签: r

我有以下载体

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

如何使用向量化操作更改v以使每个v TRUE元素的前2个元素和后2个元素也设置为TRUE?也就是说,结果应该是:

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

当然,这可以通过每个v元素上的循环来完成,但我想了解是否可以对这种操作进行矢量化。与this question不同,v中的元素是独立的,我不需要对每个元素执行计算。这是一个纯粹的索引问题。

4 个答案:

答案 0 :(得分:11)

这个排序的东西可能会像你想要的那样被矢量化:

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元素中应该发生什么。这需要更多的工作。如果有两个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 :(得分:5)

晚会......您应该应用卷积过滤器。它会比任何东西都快。唯一的困难是,在两个末端你应该预先添加/追加一对FALSE,这样过滤器就不会用NA进行初始化。这是一个可以为您完成的功能:

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

答案 2 :(得分:3)

这是另一次尝试。它似乎适用于您的数据以及第一个元素为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

答案 3 :(得分:1)

又一种方法。创建一组滞后向量,并将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))
}