R中有多个行删除范围

时间:2014-11-22 21:27:47

标签: r delete-row

我们说我有

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)}),]不会工作。

2 个答案:

答案 0 :(得分:1)

Richard Scriven的回答只返回要从v中删除的行的索引10-delta:10+delta40-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