My forloop takes many hours, is there a faster/more efficient way to do this simulation?

Hi

In advance, thank you!
I'm pretty new to R so please don't judge too much :slight_smile:

I've written a loop that is similar to a MonteCarlo simulation, my problem is that it takes 6 minutes for 100.000 loops, and 4 hours for 500.000 loops. but i don't understand why it is so ineffective.
Is there a better way to do this and obtain the same result?

#Event 1
E1LB<-200000
E1UB<-150000000
E1Chance<-0.10

#Event 2
E2LB<-50000
E2UB<-7000000
E2Chance<-0.10

#Event 3
E3LB<-20000
E3UB<-8500000
E3Chance<-0.15

#Event 4
E4LB<-2000
E4UB<-5000000
E4Chance<-0.25

#Event 1 mean and sd
LnE1LB<-log(E1LB)
LnE1UB<-log(E1UB)
meanE1<-(LnE1LB+LnE1UB)/2
sdE1<-(LnE1UB-LnE1LB)/3.29

#Event 2 mean and sd
LnE2LB<-log(E2LB)
LnE2UB<-log(E2UB)
meanE2<-(LnE2LB+LnE2UB)/2
sdE2<-(LnE2UB-LnE2LB)/3.29

#Event 3 mean and sd
LnE3LB<-log(E3LB)
LnE3UB<-log(E3UB)
meanE3<-(LnE3LB+LnE3UB)/2
sdE3<-(LnE3UB-LnE3LB)/3.29

#Event 4 mean and sd
LnE4LB<-log(E4LB)
LnE4UB<-log(E4UB)
meanE4<-(LnE4LB+LnE4UB)/2
sdE4<-(LnE4UB-LnE4LB)/3.29

#Simulation with 100.000 koops
for (k in 1:100000) {
Event1<-ifelse (runif(1)<E1Chance, qlnorm(runif(1),meanE1,sdE1), 0)
Event2<-ifelse (runif(1)<E2Chance, qlnorm(runif(1),meanE2,sdE2), 0)
Event3<-ifelse(runif(1)<E3Chance, qlnorm(runif(1),meanE3,sdE3), 0)
Event4<-ifelse(runif(1)<E4Chance, qlnorm(runif(1),meanE4,sdE4), 0)

results<- rbind(results,data.frame(Event1, Event2, Event3, Event4))
}

You just need to tweak the last part:

#Simulation with 100.000 loops
n <- 1000000
p <- runif(n)
results <- data.frame(
  Event1 = ifelse(p < E1Chance, qlnorm(p, meanE1, sdE1), 0), 
  Event2 = ifelse(p < E2Chance, qlnorm(p, meanE2, sdE2), 0), 
  Event3 = ifelse(p < E3Chance, qlnorm(p, meanE3, sdE3), 0), 
  Event4 = ifelse(p < E4Chance, qlnorm(p, meanE4, sdE4), 0)
)

The reason your code ran so slowly is that (a) it wasn't vectorised (i.e. the loop isn't required) and (b) the results dataframe was being expanded one row at a time, rather than its dimensions being defined upfront, which is very slow.

1 Like

Thank you for your input, however with this set-up the Events would not be happening independent.
For every n one random number is generated, so if that number is high, no events will happen, but if it is very low, then all will happen at once.
While I would want each event to be individual
I think i have solved it by changing your code to

#Simulation with 100.000 loops
n <- 1000000
p <- runif(n)
p1 <- runif(n)
p2 <- runif(n)
p3 <- runif(n)
p4 <- runif(n)
results <- data.frame(
Event1 = ifelse(p1 < E1Chance, qlnorm(p, meanE1, sdE1), 0),
Event2 = ifelse(p2 < E2Chance, qlnorm(p, meanE2, sdE2), 0),
Event3 = ifelse(p3 < E3Chance, qlnorm(p, meanE3, sdE3), 0),
Event4 = ifelse(p4 < E4Chance, qlnorm(p, meanE4, sdE4), 0)
)

1 Like

Yes, that change makes sense. I didn't pretend to understand what the actual problem was, just to demonstrate the R coding element.

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.