从向量中有效地删除 n 个随机条目,其中 n 可能为 0

Efficiently removing n random entries from a vector, where n may be 0

我想删除从向量中随机选择的 n 个元素,其中 n 大于或等于 0。 n 从二项式中采样,并且很小,可能为 0。 我想尽可能高效地执行此操作,因此代码可以 运行 很多次。问题是如果 n = 0.

,使用 vec[-sample(vec,n)] 可能会给出一个空向量

我有几个想法,我想知道是否有人知道解决该问题的更好或更快的方法。

  1. 使用减号,以及之前的 if 函数。
# y is a vector of length 10000
n <- rbinom(n = 1, size = 10000, p = 0.0001)
if (length(n) != 0){
   y <- y[-sample((1:10000), size = n)]
}
  1. 正在选择所有其他元素。
# y is a vector of length 10000
n <- rbinom(n = 1, size = 10000, p = 0.0001)
n <- 10000 - n
y <- sample(y, size = n)

创建一个布尔向量,指示 TRUEFALSE 是否保留每一列:

p = 0.0001
keep = sample(c(TRUE, FALSE), size = length(y), prob = c(1 - p, p), replace = TRUE)
y[keep]

你可以用 runif 做同样的事情,这可能会更快一点:

y[runif(length(y)) > p]

实际上,结果 sample 快了大约 2 倍 - 尽管因为我们测量的是微秒,所以这并不重要。

n = 10000
p = 0.0001
y = rnorm(n)

microbenchmark::microbenchmark(
  sample = y[sample(c(TRUE, FALSE), size = n, prob = c(1 - p, p), replace = TRUE)],
  runif = y[runif(n) > p]
)
# Unit: microseconds
#    expr   min     lq    mean median     uq     max neval
#  sample 128.9 195.05 463.591  297.9 346.65 15319.9   100
#   runif 349.0 565.80 876.925  674.3 800.55  6990.6   100