高效地从一个向量中随机删除n个元素,其中n可能为0。

3

我想从一个向量中随机选择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)]
}

2. 选择所有其他元素。
# y is a vector of length 10000
n <- rbinom(n = 1, size = 10000, p = 0.0001)
n <- 10000 - n
y <- sample(y, size = n)
1个回答

4
创建一个布尔向量,指示每列是否保留:TRUE表示保留,FALSE表示不保留:
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]

实际上,结果发现样本更快,大约快了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

另外一种可能是 rbinom(n, 1, 1 - p),但速度较慢。 - jay.sf
1
@jay.sf 需要使用 as.logical() 包装器。 (这不需要任何时间) - Gregor Thomas
@GregorThomas 是的,也包括那个! - jay.sf

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接