首页 文章

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

提问于
浏览
0

我有两个逻辑向量 xy 以及与每个索引对应的加权值 z . 对于 TRUEx 列,我想找到最接近的 y 列索引,也是 TRUE . 然后在min { x_iy_i }之间抓取 sumz . 如果有两分钟{ x_iy_i }则使用 z 的较小 sum .

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

有3个 x 值是 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 回答

  • 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]
    }
    

    修订:一些改进 .

相关问题