【问题标题】:Efficiently removing n random entries from a vector, where n may be 0有效地从向量中删除 n 个随机条目,其中 n 可能为 0
【发布时间】:2021-01-22 15:03:20
【问题描述】:

我想删除从向量中随机选择的 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)

【问题讨论】:

    标签: r performance syntax


    【解决方案1】:

    创建一个布尔向量,指示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
    

    【讨论】:

    • 也可以rbinom(n, 1, 1 - p),但速度较慢。
    • @jay.sf 这也需要as.logical() 包装器。 (并不是说这需要任何时间)
    • @GregorThomas 是的,那个也是!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-24
    • 2014-09-29
    • 2022-12-04
    • 1970-01-01
    • 2019-11-22
    • 1970-01-01
    相关资源
    最近更新 更多