Iason
Iason

Reputation: 39

Sampling iteratively without a for loop in R

Even though I think the issue I have may be simple, I nevertheless can't figure it out. Here's the thing:

I have the following list and vector. The list is used to fill up the vector:

probabilities = list(c(0.2, 0.3, 0.5), c(0.1, 0.1, 0.8), c(0.3,0.4,0.3))
nextState = c()

for(counter in 1:3){
nextState[counter] = sample(1:3, size = 1, prob = probabilities[[counter]])
}

The code works fine. However, when expanding to larger lists (>10,000 elements), the loop becomes aggravatingly slow. Since the loop above is used multiple times in the larger code, the time consumed is way too much. Would there be a way to achieve the same result without looping?

Additional question:

Thanks guys, you've been a big help. One additional question: How would approach the same issue if the probabilities and the nextState were interdependent Meaning, how could I avoid the for loop? Perhaps some code to clarify:

M <- list(matrix(c(0.1, 0.2, 0.7, 0.2, 0.2, 0.6, 0.3, 0.3, 0.4), nrow = 3, ncol = 3), 
         matrix(c(0.3, 0.3, 0.4, 0.5, 0.5, 0, 0.1, 0.1, 0.8), nrow = 3, ncol = 3))

probabilities <- list()
nextState <- c(2, NA, NA)

for(i in 1:2){
probabilities[[i]] <- M[[i]][nextState[i], ]
nextState[i + 1] <- sample(1:3, size = 1, prob = probabilities[[i]])
}

If you've got any idea, then you truly are miracle workers!!

Upvotes: 0

Views: 251

Answers (2)

RLave
RLave

Reputation: 8364

Another possibility with purrr package:

library(purrr)

nexstate <- map_int(probabilities, function(x) {sample(1:3, size = 1, prob = x)})

Data:

probabilities = list(c(0.2, 0.3, 0.5), c(0.1, 0.1, 0.8), c(0.3,0.4,0.3))

Upvotes: 0

Wimpel
Wimpel

Reputation: 27732

try sapply

nextstate <- sapply( probabilities, function(x) {sample(1:3, size = 1, prob = x)})

benchmarks

# Unit: microseconds
#   expr      min       lq      mean    median       uq      max neval
#    for 2115.170 2223.475 2436.0797 2283.2755 2371.546 10048.64   100
# sapply   24.704   29.524  164.0261   37.3565   41.123 12763.03   100


microbenchmark::microbenchmark(
  `for` = { 
    nextState = c()
    for(counter in 1:3){
      nextState[counter] = sample(1:3, size = 1, prob = probabilities[[counter]])
    }
  },
  sapply = sapply( probabilities, function(x) {sample(1:3, size = 1, prob = x)}),
  times = 100)

Upvotes: 1

Related Questions