我们说我有
v <- matrix(seq(150), 50, 3)
k <- c(10, 40)
delta <- 5
如何同时删除10-delta到10 + delta行和40-delta到40 + delta行?
我使用vnew <- v[-((k-delta):(k+delta)),]
但似乎该命令仅使用k的第一个元素(即10)删除,并且不删除40-delta到40 + delta行。有谁知道怎么做?
哦,我需要把它放在一个循环中,每次迭代都会更新k
,所以v[c(-{(10-delta):(10+delta)},-{(40-delta):(40+delta)}),]
不会工作。
答案 0 :(得分:1)
Richard Scriven的回答只返回要从v中删除的行的索引10-delta:10+delta
和40-delta:40+delta
。为了有效地执行此操作,您必须将它与您尝试的内容结合起来:
v[-c(sapply(seq(k), function(i) (k[i]-delta):(k[i]+delta))), ]
或更短但更脏(?):v[-sapply(seq(k), function(i) (k[i]-delta):(k[i]+delta)), ]
答案 1 :(得分:1)
如果k
在每次迭代中都在增长且delta
没有变化,我建议如下:
d <- -delta:delta
for (...) {
# ...
vnew <- v[-(rep(k, each=length(d)) + d),]
# ...
}
对于你的例子:
d <- -5:5
k <- c(10, 40)
rep(k, each=length(d)) + d
# [1] 5 6 7 8 9 10 11 12 13 14 15 35 36 37 38 39 40 41 42 43 44 45
编辑:两种解决方案的基准:
library("rbenchmark")
idx1 <- function(k, delta) {
d <- -delta:delta
lapply(seq_along(k), function(i) {
rep(k[1:i], each=length(d)) + d
})
}
idx2 <- function(k, delta) {
lapply(seq_along(k), function(i) {
c(sapply(1:i, function(ii) {
(k[ii]-delta):(k[ii]+delta)
}))
})
}
set.seed(1)
k <- sample(1e3, 1e2)
delta <- 5
all.equal(idx1(k, delta), idx2(k, delta))
# [1] TRUE
benchmark(idx1(k, delta), idx2(k, delta), order="relative", replications=100)
# test replications elapsed relative user.self sys.self user.child sys.child
# 1 idx1(k, delta) 100 0.174 1.000 0.172 0 0 0
# 2 idx2(k, delta) 100 1.579 9.075 1.576 0 0 0