1
\$\begingroup\$

I have written a function/script to simulate data for sample size estimation. The following code samples from a vector of generated values with varying numbers of sample sizes and then concatenates means and standard deviations for a number of simulations.

I am using nested loops but would like to vectorize the code for efficiency and am wondering if anyone could suggest some optimizations.

library(MCMCglmm)
library(tidyverse)

Est <- function(n, mean, sd, lower, upper, samp_min, samp_max, samp_int, nsim){

        Data <- round(rtnorm(n, mean, sd, lower, upper), digits = 0) # Create a vector to sample from

        Samp_size <- seq(samp_min, samp_max, samp_int) # Create vector of sample sizes

        # Set up enpty results data frames
        Results_samp <- data.frame()
        Results <- data.frame()

        for(i in 1:nsim){ ## Loop through number of simulations

                for (j in seq_along(Samp_size)) { # Loop through sample sizes
                     SUS_Score <- sample(Data, Samp_size[j], replace = TRUE)
                     Nsubj <- Samp_size[j]
                     Mean <- mean(SUS_Score, na.rm = TRUE)
                     SD <- sd(SUS_Score, na.rm = TRUE)
                     Results_samp <- rbind(Results_samp, 
                                      data.frame(
                                              Nsubj,
                                              Mean,
                                              SD))
                }
             Results <- rbind(Results, Results_samp) 
             Results_samp <- data.frame()
        }

       Results %>%
               arrange(Nsubj)
}

Sims <- Est(n = 1000, mean = 55, sd = 37, lower = 0, upper = 100, samp_min = 5, samp_max = 35, samp_int = 5, nsim = 1000)

Any suggestions would be greatly appreciated!

\$\endgroup\$
1
\$\begingroup\$

Your code is quite good. Simulations is hard to vectorize. The largest slowdown here is the repeated calling of rbind in loop. It is faster to crate list of vectors and concatenate the results at the end. So I edited the necessary parts:

Est3 <- function(n, mean, sd, lower, upper, samp_min, samp_max, samp_int, nsim) {
  Data <- round(rtnorm(n, mean, sd, lower, upper), digits = 0)
  Samp_size <- seq(samp_min, samp_max, samp_int)
  Results <- list() # crate emty list
  for (i in 1:nsim) {
    Results_samp <- list() # crate emty list
    for (j in seq_along(Samp_size)) {
      Nsubj <- Samp_size[j]
      SUS_Score <- sample(Data, Nsubj, replace = TRUE)
      Mean <- mean(SUS_Score, na.rm = TRUE)
      SD <- sd(SUS_Score, na.rm = TRUE)
      Results_samp[[j]] <- c(Nsubj, Mean, SD) # add values to list
    }
    Results[[i]] <- Reduce(rbind, Results_samp) # convert list to matrix and add to main list
  }
  Results <- Reduce(rbind, Results) # 'rbind' list of matrices
  Results <- as.data.frame(Results, row.names = F) # convert to data.frame
  colnames(Results) <- c('Nsubj', 'Mean', 'SD') # add names
  Results %>% arrange(Nsubj)
}
| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.