我有两个逻辑向量x
和y
以及与每个索引对应的加权值z
。对于x
列TRUE
,我想查找最近的y
列索引TRUE
。然后在min {sum
,z
}之间抓住x_i
y_i
。如果有两分钟{x_i
,y_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_1
,x_2
,x_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
我更愿意将解决方案保留在基础之内。
答案 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]
}
修订:一些改进。