Reputation:
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))
Upvotes: 1
Views: 228
Reputation: 9087
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
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)
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)))
Upvotes: 3