两个逻辑向量中元素之间的最小距离

时间:2014-02-01 03:09:16

标签: r

我有两个逻辑向量xy以及与每个索引对应的加权值z。对于xTRUE,我想查找最近的y列索引TRUE。然后在min {sumz}之间抓住x_i y_i。如果有两分钟{x_iy_i},则会使用较小的sum z

       x     y          z
1  FALSE  TRUE 0.05647057
2  FALSE FALSE 0.09577802
3   TRUE FALSE 0.04150954
4  FALSE FALSE 0.07242995
5  FALSE  TRUE 0.06220041
6  FALSE FALSE 0.01861535
7  FALSE FALSE 0.05056971
8   TRUE FALSE 0.07726933
9  FALSE  TRUE 0.04669694
10  TRUE  TRUE 0.02312497

x有3个TRUE个值,因此我们称之为{x_1x_2x_3}。在这里,我演示了每个x_i和它最近的y_i邻居之间的最小索引的总和。什么是实现这一目标的最有效的基础R方式。最后我有一个方法利用2 lapply告诉我它可能效率不高。我没有数学背景,通常有一些代数方法可以完成这些任务,这些任务是通过强大的计算能力进行矢量化的。

## x_1
sum(z[3:5]) ## This one is smaller so use it
sum(z[1:3])

## x_2
sum(z[8:9])

## x_3
sum(z[10])

c(sum(z[3:5]), sum(z[8:9]), sum(z[10]))
[1] 0.17613990 0.12396627 0.02312497

MWE

x <- y <- rep(FALSE, 10)
x[c(3, 8, 10)] <- TRUE
y[c(1, 5, 9, 10)] <- TRUE
set.seed(15)
z <- rnorm(10, .5, .25)/10
data.frame(x=x, y=y, z=z)

这是一种不太理想的方法:

dat <- data.frame(x=x, y=y, z=z)
sapply(which(dat[, "x"]), function(x) {
    ylocs <- which(dat[, "y"])
    dists <- abs(x - ylocs)
    min.ylocs <- ylocs[min(dists) == dists]
    min(sapply(min.ylocs, function(y, x2 = x) {
        sum(dat[, "z"][x2:y])
    }))
})

## [1] 0.17613990 0.12396627 0.02312497

我更愿意将解决方案保留在基础之内。

1 个答案:

答案 0 :(得分:3)

这不使用循环或应用函数。我们使用动物园中的na.locf将最后一个TRUE的y的索引移到fwd,将下一个TRUE y移回bck。最后,我们确定两个相应的总和中哪一个更大。这取决于动物园包中的na.locf,但最后我们 从动物园中提取核心代码以避免依赖:

library(zoo) # na.locf

x <- dat$x
y <- dat$y
z <- dat$z

yy <- ifelse(y, TRUE, NA) * seq_along(y)
fwd <- na.locf(yy, fromLast = FALSE)[x]
bck <- na.locf(yy, fromLast = TRUE)[x]

cs <- cumsum(z)
pmin(cs[x] - cs[fwd] + z[fwd], cs[bck] - cs[x] + z[x])

最后一行给出:

[1] 0.17613990 0.12396627 0.02312497

以下是na.locf的迷你版。上面的库调用可以替换为。

# code extracted from zoo package
na.locf <- function(x, fromLast = FALSE) {
   L <- !is.na(x)
   if (fromLast) rev(c(NA, rev(which(L)))[cumsum(rev(L)) + 1])
   else c(NA, which(L))[cumsum(L)+1L]
}

修订:一些改进。