5

I am trying to write a nested loop code to simulate 10 columns of data in a data frame with 101 rows. The first row of data has been assigned as starting values. Each column should be different as my matrix r is generated from random normals; however, the resulting values in each column are exactly the same. To give some context for the looping indices:

tmax=100; ncol(pop_sims) = 12 (so a total of 10 iterations, 3-12); ncol(r) = 10

for (i in 1:tmax){
 for (j in 3:ncol(pop_sims)){
   for(k in 1:ncol(r)){

   if (pop_sims[i,j]*exp(r[i,k]) <2) {
    pop_sims[i+1,j]<- 0} 
  else {
      pop_sims[i+1,j] <- pop_sims[i,j]*exp(r[i,k])}
}}} 

Any thoughts would be appreciated.

UPDATE: Instead of working with the multiple loops, I omitted the use of the matrix r and simplified my loops.

for (i in 1:tmax){
 for (j in 1:10){

  if (pop_sims[i,j]*exp(r[i,j]) <2) {
    pop_sims[i+1,j]<- 0} 
  else {
      pop_sims[i+1,j] <- pop_sims[i,j]*exp(rnorm(1,mean=0.02, sd=0.1))}
}}
Tiffany
  • 301
  • 1
  • 2
  • 12
  • Inside your third loop, you overwrite `pop_sims[i+1,j]` for each value of `k`. Therefore, `pop_sims[i+1,j]` will be set based on the value `k=ncol(r)`; you'd might as well not have even used the inner loop. Can you briefly describe what you're trying to accomplish? – josliber Jan 08 '14 at 16:12
  • Yes, I'm trying to set pop_sims[i+1,j] to the previous (same column, previous row) value multiplied by the random normal r at the same column and row designation (from matrix r) of the cell being updated. Ideally, every r value will be used once. Does that make sense? Is there a way to accomplish this inside the loop? – Tiffany Jan 08 '14 at 16:18
  • @josilber I updated as above. I see what you mean. I can't think of how to remedy this from the loop, so I just reorganized how I was approaching the problem. Thanks for recognizing the problem! – Tiffany Jan 08 '14 at 16:24

1 Answers1

3

Looping is almost never the best way to accomplish a task in R. It sounds like you want to multiply some initial value by the cumulative product of random numbers, and store this as the columns of a matrix. cumprod is how to get a cumulative product in R:

tmax = 100
initial.row = 1:10
rbind(initial.row, sapply(initial.row,
                          function(x) x*cumprod(exp(rnorm(tmax-1, mean=.02, sd=.1)))))

#                 [,1]       [,2]      [,3]     [,4]      [,5]      [,6]       [,7]       [,8]      [,9]     [,10]
# initial.row 1.000000   2.000000  3.000000 4.000000  5.000000  6.000000   7.000000   8.000000  9.000000 10.000000
#             1.211479   2.483438  3.376012 3.684407  5.611144  5.689530   6.115748   7.809380  8.364223 10.748108
#             1.221254   2.832064  3.500622 3.417095  5.047067  5.706181   6.445985   9.031854  8.125584 10.115107
#             1.350398   3.002284  3.723416 3.581471  5.121880  7.300373   8.008373  10.679728  7.167270 10.310810
#             1.269193   2.883153  3.546245 3.160029  5.312947  7.983395   6.986608  11.226517  7.166026  9.195459
#             ...
josliber
  • 43,891
  • 12
  • 98
  • 133
  • Wow, that looks great. I still need to build in my if statement, but I'm sure I can figure that out. This is a much more efficient way. Thank you. – Tiffany Jan 08 '14 at 16:40
  • Keep in mind that applying sapply() with rbind() is simply a cleaner looking for loop. To get beyond loops, you need to look to vector/matrix operations. – Adam Erickson Jan 19 '16 at 23:06