9

我有以下向量

 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 元素上循环来完成,但我想了解是否可以对这种操作进行矢量化。也不同于这个问题, v 中的元素是独立的,我不需要对每个元素执行计算。这是一个纯粹的索引问题。

4

4 回答 4

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

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

于 2013-04-24T19:43:35.010 回答
5

迟到了...你应该应用卷积过滤器。它会比什么都快。唯一的困难是在两端你应该预先/附加一对FALSE,这样过滤器就不会用NAs 初始化。这是一个可以为您完成的功能:

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
于 2013-04-25T02:08:34.187 回答
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
于 2013-04-24T20:31:01.263 回答
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))
}
于 2013-04-25T03:07:43.523 回答