[R] Simplify the loop over the 3rd dimension of a 3D array

David Winsemius dw|n@em|u@ @end|ng |rom comc@@t@net
Thu Jul 12 20:21:53 CEST 2018


> On Jul 12, 2018, at 9:40 AM, Duncan Murdoch <murdoch.duncan using gmail.com> wrote:
> 
> On 12/07/2018 11:34 AM, Marine Regis wrote:
>> Hello all,
>> Is there an efficient way to simplify the loop over the 3rd dimension of a 3D array ? I want to keep the loop over the "time". Here is the code:
>> set.seed(12345)
>> ind <- 10
>> time_seq <- seq(0, 8, 1)
>> col_array <- c(paste("time_", time_seq, sep=""))
>> tab <- array(0, dim=c(length(time_seq) , length(col_array), ind), dimnames=list(NULL, col_array, as.character(seq(1, ind, 1))))
>> print(tab)
>> tab[1,c("time_0"),] <- round(runif(ind, 0, 100))
>> print(tab)
>> for(time in 1:(length(time_seq) - 1)){
>>   for(i in 1:ind){
>>     tab[time + 1,c("time_0"),i] <- round(runif(1, 0, 100))
>>     tab[time + 1,c("time_1"),i] <- tab[time,c("time_0"),i]
>>     tab[time + 1,c("time_2"),i] <- tab[time,c("time_1"),i]
>>     tab[time + 1,c("time_3"),i] <- tab[time,c("time_2"),i]
>>     tab[time + 1,c("time_4"),i] <- tab[time,c("time_3"),i]
>>     tab[time + 1,c("time_5"),i] <- tab[time,c("time_4"),i]
>>     tab[time + 1,c("time_6"),i] <- tab[time,c("time_5"),i]
>>     tab[time + 1,c("time_7"),i] <- tab[time,c("time_6"),i]
>>     tab[time + 1,c("time_8"),i] <- tab[time,c("time_7"),i]
>>   }
>> }
> 
> It looks as though you are setting all entries to the same value.

I agree that it looked like that to me as well but in testing with a slight smaller version of the array I found that it was not so simple. I shortended the arrae to be dim = c(3,5,5) so that I could see it on one page, and then ran the code:

> for(time in 1:(length(time_seq) - 1)){
+  for(i in 1:ind){
+    tab[time + 1,c("time_0"),i] <- round(runif(1, 0, 100))
+    tab[time + 1,c("time_1"),i] <- tab[time,c("time_0"),i]
+    tab[time + 1,c("time_2"),i] <- tab[time,c("time_1"),i]
+    tab[time + 1,c("time_3"),i] <- tab[time,c("time_2"),i]
+    tab[time + 1,c("time_4"),i] <- tab[time,c("time_3"),i]
+    
+  }
+ }
> 
> print(tab)
, , 1

     time_0 time_1 time_2 time_3 time_4
[1,]     72      0      0      0      0
[2,]     89     72      0      0      0
[3,]     33     89     72      0      0
[4,]     99     33     89     72      0
[5,]     74     99     33     89     72

, , 2

     time_0 time_1 time_2 time_3 time_4
[1,]     88      0      0      0      0
[2,]     46     88      0      0      0
[3,]     51     46     88      0      0
[4,]      3     51     46     88      0
[5,]      0      3     51     46     88

, , 3

     time_0 time_1 time_2 time_3 time_4
[1,]     76      0      0      0      0
[2,]     17     76      0      0      0
[3,]     73     17     76      0      0
[4,]     15     73     17     76      0
[5,]     39     15     73     17     76


So the code was filling in the diagonal and a shifter version of the diagonal values. Whether that was the intent of the OP was not clear from the original email. The practice of throwing code as the only description of the problem is a common source of confusion.





> A simpler way to do that would be this loop:
> 
> for(time in 1:(length(time_seq) - 1)){
>  for(i in 1:ind){
>    tab[time + 1,,i] <- round(runif(1, 0, 100))
>  }
> }
> 
> You could also do away with the inner loop by generating ind random values all at once.  You have to be a little careful with the ordering; I think this gets it right:
> 
> for(time in 1:(length(time_seq) - 1)){
>  tab[time + 1,,] <- t(matrix(round(runif(ind, 0, 100)), ind, 9))
> }
> 
> And then you can do away with the loop entirely, since none of the values depend on earlier calculations.  Just generate ind*length(time_seq) uniforms, and put them in the array in the right order.  You could use aperm() to do this instead of t(), but be careful, it's easy to get the permutation wrong.  (I'm not even going to try now. :-).
> 
> Duncan Murdoch
> 
>> print(tab)
>> In fact, the array has 800000 observations for the 3rd dimension.
>> Many thanks for your time
>> Have a great day
>> Marine
>> 	[[alternative HTML version deleted]]
>> ______________________________________________
>> R-help using r-project.org mailing list -- To UNSUBSCRIBE and more, see
>> https://stat.ethz.ch/mailman/listinfo/r-help
>> PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
>> and provide commented, minimal, self-contained, reproducible code.
>> 
> 
> ______________________________________________
> R-help using r-project.org mailing list -- To UNSUBSCRIBE and more, see
> https://stat.ethz.ch/mailman/listinfo/r-help
> PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
> and provide commented, minimal, self-contained, reproducible code.

David Winsemius
Alameda, CA, USA

'Any technology distinguishable from magic is insufficiently advanced.'   -Gehm's Corollary to Clarke's Third Law




More information about the R-help mailing list