Optimisation of sampling without replacement

Viewed 87

Is there any way to make this considerably faster?

out1 <- sapply(1:1e6, function(ii) sample.int(10, 10, replace = FALSE) )

Any help greatly appreciated!

1 Answers

The bottleneck here is the repeated call to sample.int, and unless you can get rid of it, I doubt the call will be much faster. Would you ever need to sample from larger vectors (i.e. with more than 10 elements)? Because if not, you could precompute all the permutions and then sample from them. For 10 elements, there are only 3628800 permutations.

x <- sapply(1:1e6, function(ii) sample.int(10, 10, replace = FALSE) )

A version without sapply.

rand_x <- function(samples = 1e6, size = 10) {
    ans <- numeric(samples*size)
    dim(ans) <- c(size, samples)

    for (i in seq_len(samples))
        ans[, i] <- sample.int(size)
    ans
}

Precomputing combinations.

library("combinat")
C <- permn(1:10)
C <- do.call(cbind, C)
## int [1:10, 1:3628800] 1 2 3 4 5 6 7 8 9 10 ...

rand_x2 <- function(samples = 1e6, C) {
    p <- sample.int(ncol(C), samples, replace = TRUE)
    C[, p]
}

Comparing speeds.

library("rbenchmark")
benchmark(sapply(1:1e6, function(ii) sample.int(10, 10, replace = FALSE) ),
          rand_x(),
          rand_x2(C = C),
          replications = 5, order = "relative")

##                   test replications elapsed relative user.self
## 3       rand_x2(C = C)            5   0.633    1.000     0.634
## 2             rand_x()            5  14.352   22.673    14.351
## 1 sapply(1:1e+06, ...)            5  18.435   29.123    18.422
Related