1

In R, for a school project, I am trying to turn a function that uses a for loop to a function that uses the apply function.

My function simulates a Poisson distribution where the person can enter the parameters n, lambda and m. m is the number of simulations. It then outputs the mean of all of the means of the m Poisson simulations and outputs a 2x2 grid of box plots so the user can show multiple plots with different parameter values. It is posted below.

I struggling to figure out how to turn this into a function that uses the apply function. As apply needs a matrix, would I need to already have a matrix m.out for certain parameter values from my for loop function. Also, I am not sure exactly what the function would be using apply. I would want to take the mean of every value in the matrix.

Any help is appreciated.

Venom<-function(n,l,m){
  if(!is.numeric(c(n,l,m))){return("Error non-numeric value entered for at `enter code here`least one parameter")}
    m.out<-NULL
    for(i in 1:m){
      data1<-rpois(n,l)
      m.sim<-mean(data1)
      m.out<-rbind(m.out, m.sim)
    }
    finalmean<-mean(m.out)
    hist(m.out, main=paste("Poisson n=",n))
    return(c(finalmean, m.out))
}
par(mfrow=c(2,2))
0

1 Answer 1

3

Here are a few base R and tidyverse alternatives to the for loop.

set.seed(0)
n = 10
l = 5
m = 20

First, here's your original loop. I replaced rbind with c as m.out is being treated as a vector rather than a matrix.

m.out <- NULL
for(i in 1:m){
  data1 <- rpois(n,l)
  m.sim <- mean(data1)
  m.out <- c(m.out, m.sim)
}
print(m.out)
#  [1] 6.1 5.1 4.9 5.0 5.3 4.4 4.8 5.8 4.7 5.2 5.5 4.6 5.2 5.2 4.4 4.5 5.1 5.7 6.0 4.7

Base R

As you mentioned, apply takes a matrix. However, sapply can use vectors as input and output.

sapply(seq_len(m), function(x) {
  mean(rpois(n, l))
})

Another base R solution is to use replicate which will repeat an expression m times. simplify = T will make it output a vector rather than a list.

replicate(
  m,
  mean(rpois(n, l)),
  simplify = T)

Tidyverse

rerun is purrr's version of replicate. It will produce a list, so we need to unlist the result.

library('tidyverse')
rerun(m, mean(rpois(n, l))) %>%
  unlist

Another way is to use map_dbl which will apply a function to each element in the vector and return a vector of doubles.

map_dbl(seq_len(m), ~mean(rpois(n, l)))
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.