0
votes

I want perform log-normal monte-carlo simulations for 12 iterations with location and shape of distribution varying for each iteration. As an output of the following code I want each simulation result in a different columns as a data frame. For instance, if I want to perform 10,000 simulations for each set of location and shape, the resultant data frame will have 12 columns and 10000 rows. I wrote the code in two parts where I first defined the function for lapply and then tried to perform simulation with results from each iteration being stored into a different column. Part 1 code:

myfxn <- function(i,s,location,shape){
cvsq=1
  i <-seq(5,60,5)
  s <-i*cvsq
  location <- log(i^2 / sqrt(s^2 + i^2))
  shape <- sqrt(log(1 + (s^2 / i^2)))
}

Part 2 code:

DF1 <- do.call(cbind, lapply(seq(5,60,5), function(myfxn) setNames(data.frame(rlnorm(n=10000, location, shape)), i)))
head(DF1)

The issue is I keep getting errors with the defined function.

1
In the part 2 code, you are applying myfxn as a anonymous functionakrun
Also, in the function myfxn, the arguments specified are i, s, location, shape, while those are objects created within the function?akrun

1 Answers

0
votes

You seem to be confused about your function declaration. Your function looks as though it should take 4 parameters (i, s, location and shape). However, inside the function these inputs are never used - they are all created from scratch according to the value of cvsq. They are therefore redundant as inputs to the function.

Inside your lapply, you are passing the values seq(5,60,5) to your function, but it isn't clear what these are for if the variables i, s, location and shape are all calculated anew every time the function is called. What is it you want your function to do with these numbers?

My guess is that you want to feed a single number into your function and have it alter these variables. If so, the only variable it makes sense to have being passed as a single parameter is cvsq, since altering cvsq alters the value of all the other variables. If this is wrong, then it's just not clear what you're trying to do.

If I'm on the right track, your code would look like this:

myfxn <- function(cvsq)
{
  i <-seq(5,60,5)
  s <-i*cvsq
  location <- log(i^2 / sqrt(s^2 + i^2))
  shape <- sqrt(log(1 + (s^2 / i^2)))
  rlnorm(n = 10000, location, shape)
}

my_cvsq <- seq(5, 60, 5)
df <- as.data.frame(do.call(cbind, lapply(my_cvsq, myfxn)))

head(df)
#>           V1        V2         V3        V4         V5        V6           V7
#> 1  0.1786204 1.2587228 0.04588056 1.1925041 0.01985825 0.6924621 0.0008467456
#> 2 28.6147331 0.1243106 0.08306054 0.5057983 4.65819135 3.0851280 0.0429381886
#> 3  0.6666314 0.5546972 2.83435439 0.6512173 0.04994503 6.4365528 0.3779170170
#> 4  7.7163909 4.5954509 0.26637679 0.4085584 3.31589074 0.4894957 1.5195320720
#> 5  1.0931151 0.0575365 0.80689457 0.5033203 1.35200408 0.1427171 2.4058576253
#> 6  0.2573164 7.6190362 1.01222386 1.8598690 5.91525940 0.5600217 0.7858050404
#>            V8         V9        V10         V11       V12
#> 1 1.263350450 0.09485695 0.02615021 0.331885430 2.9109114
#> 2 0.004408080 0.14120821 0.05990997 0.053248650 0.1013357
#> 3 0.888602537 1.32448399 1.17625454 0.766153864 0.0196438
#> 4 5.254249758 0.01337194 0.08463637 2.996341976 0.8942556
#> 5 0.004375628 0.05052838 0.51024824 0.533356862 1.6166927
#> 6 0.985499853 0.09939285 0.86272478 0.001223073 1.0652496

And we can see what your 12 samples look like by plotting their density:

d <- density(df[,1], from = 0, to = 10)
plot(d$x, d$y, type = "l", xlim = c(0, 10), ylim = c(0, 0.7))
for(i in 2:12){
  d <- density(df[,i], from = 0, to = 10)
  lines(d$x, d$y, col = i)
}

Created on 2020-07-11 by the reprex package (v0.3.0)