Filling 3D-Array with for loop in R (by rows and for each matrix)

Hey,
I am a beginner in R and have some challenges in filling of 3D array.
Data:
fkt.P=function(P,L) {

                 X.Re=numeric(length(S.1))
                 for(i in 1:length(S.1)){ 
               	  X.Re[i]=min(max(S.1[i]-P,0),L)}
                 
                   pi.s=mean(S.1)*(1+load.S)
                   pi.re=mean(X.Re)*(1+load.Re)
                   A.0=EC.0+pi.s-pi.re
                   alpha.rf=0.6
                   alpha.DB=0.5*(1-alpha.rf) 
                   alpha.BMW=1-alpha.rf-alpha.DB
                     A.1=A.0*exp(alpha.DB*r.DB+alpha.BMW*r.BMW+alpha.rf*rf
                    RBC.1=A.1-S.1+X.Re
                    SP.1=numeric(length(RBC.1))
                    for( i in 1:length(RBC.1)){ 
                    if(RBC.1[i]<0)
                    {SP.1[i]=1} 
                    else{SP.1[i]=0}
                            }
                           and so on.......
              return(c(RBC.1,  SP.1, and other variables))

}

P_seq=seq(0,300,100)
L_seq=seq(0,200,100)

res=array(c(0,0), dim=c(length(P_seq),7,length(L_seq))) #emty array with nrow=length(P_seq), #ncol=7, #number of matrices =length(L_seq)

I have to fill the empty array with information (by rows for each matrix)
My Idea:
for (k in 1:length(P_seq)){for (j in 1:length(L_seq)) {res[k,,j] = fkt.P(P_seq[k],L_seq[j])}}

Result: I have the same numbers in first matrix.

What could be the problem? Thank you in advance.

It's hard to say without a reproducible example, I think the problem comes from the function. The version you posted doesn't work (e.g. S.1 is used but not defined anywhere, also your exp( parenthesis is never closed), but, assuming it does return a vector of length 7, it should work.

For example, using your code and a simplified function to help see what happens:


fkt.P <- function(x,y){
  paste(x, y, 1:7, sep = "-")
}

# example of what the function does
fkt.P(3,5)
#> [1] "3-5-1" "3-5-2" "3-5-3" "3-5-4" "3-5-5" "3-5-6" "3-5-7"

P_seq=seq(0,300,100)
L_seq=seq(0,200,100)

res=array(c(0,0), dim=c(length(P_seq),7,length(L_seq))) 

for (k in 1:length(P_seq)){
  for (j in 1:length(L_seq)) {
    res[k,,j] = fkt.P(P_seq[k],L_seq[j])
  }
}

# Results
P_seq
#> [1]   0 100 200 300
L_seq
#> [1]   0 100 200
res
#> , , 1
#> 
#>      [,1]      [,2]      [,3]      [,4]      [,5]      [,6]      [,7]     
#> [1,] "0-0-1"   "0-0-2"   "0-0-3"   "0-0-4"   "0-0-5"   "0-0-6"   "0-0-7"  
#> [2,] "100-0-1" "100-0-2" "100-0-3" "100-0-4" "100-0-5" "100-0-6" "100-0-7"
#> [3,] "200-0-1" "200-0-2" "200-0-3" "200-0-4" "200-0-5" "200-0-6" "200-0-7"
#> [4,] "300-0-1" "300-0-2" "300-0-3" "300-0-4" "300-0-5" "300-0-6" "300-0-7"
#> 
#> , , 2
#> 
#>      [,1]        [,2]        [,3]        [,4]        [,5]        [,6]       
#> [1,] "0-100-1"   "0-100-2"   "0-100-3"   "0-100-4"   "0-100-5"   "0-100-6"  
#> [2,] "100-100-1" "100-100-2" "100-100-3" "100-100-4" "100-100-5" "100-100-6"
#> [3,] "200-100-1" "200-100-2" "200-100-3" "200-100-4" "200-100-5" "200-100-6"
#> [4,] "300-100-1" "300-100-2" "300-100-3" "300-100-4" "300-100-5" "300-100-6"
#>      [,7]       
#> [1,] "0-100-7"  
#> [2,] "100-100-7"
#> [3,] "200-100-7"
#> [4,] "300-100-7"
#> 
#> , , 3
#> 
#>      [,1]        [,2]        [,3]        [,4]        [,5]        [,6]       
#> [1,] "0-200-1"   "0-200-2"   "0-200-3"   "0-200-4"   "0-200-5"   "0-200-6"  
#> [2,] "100-200-1" "100-200-2" "100-200-3" "100-200-4" "100-200-5" "100-200-6"
#> [3,] "200-200-1" "200-200-2" "200-200-3" "200-200-4" "200-200-5" "200-200-6"
#> [4,] "300-200-1" "300-200-2" "300-200-3" "300-200-4" "300-200-5" "300-200-6"
#>      [,7]       
#> [1,] "0-200-7"  
#> [2,] "100-200-7"
#> [3,] "200-200-7"
#> [4,] "300-200-7"

Created on 2020-12-13 by the reprex package (v0.3.0)

So it looks to me like your for loops do what you want, but the function doesn't?

EDIT: also, a few things that shouldn't change the results, but that can improve performance and style (thus, ease to debug):

  1. The loop at the bottom of the function for(i in ...){ if(RBC.1[i] == 0) SP.1[i] = 1; else SP.1[i] = 0} can be improved as SP.1 <- ifelse(RBC.1 < 0, 1, 0)
  2. for(i in 1:length(x)) is correct, but it's safer to use for(x in seq_along(x)) (case when length(x) is 0)
  3. the alpha.XXX values could be defined once outside the function, so that you don't need to recompute them at each iteration
  4. also, I'm not sure since I don't know what S.1 looks like, but you might be able to compute x.Re at once without a loop using pmin() and pmax().
1 Like

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

If you have a query related to it or one of the replies, start a new topic and refer back with a link.