user1687130
user1687130

Reputation: 1881

loop within a loop in R

I'm trying to write a loop within a loop in R, but it seems only the inner loop is working:

test <- rbind(c(1:30), c(31:60), c(61:90), c(91:120))

Here's what I've been written:

b<- data.frame()
n<-1
i<-1
c<- data.frame()

while(i<=4){
    while(n<=10) {
        a<-cbind(test[i, 3*n-2], test[i, 3*n-1], test[i,3*n])
        b<-rbind(b,a); n<-n+1
    } ; i<-i+1; c<-cbind(c,b)
}

Basically what I'm trying to do is to group each line by three columns and transform it into multiple lines, and then do it to every line and bind these columns.

My desired output would look like:

   1  2  3  31  32  33  61  62  63  81  82  83
   4  5  6  34  35  36  64  65  66  84  85  86
   7  8  9  37  38  39  67  68  69  ......
  10 11 12  40  41  42  ......
  13 14 15  43  45  46
  16 17 18 ......
  19 20 21
  22 23 24
  25 26 27
  28 29 30  58  59  60  78  79  80  118 119 120

However what I have written only work for the first line, apparently the outer loop doesn't work. What's wrong with it please?

edit: Here's what I further tried in response to the for loop:

b<- data.frame()
c<- data.frame()
for(i in seq(from = 1, to = 4, by =1)){
    for( n in seq(from=1, to=10, by=1)) {
        a <- cbind(test[i, 3*n-2], test[i, 3*n-1], test[i,3*n])
        b <- rbind(b,a)
    }
        c <- cbind(c,b)
}

But I still could not make it work. what's wrong with it?

Upvotes: 0

Views: 4618

Answers (1)

Simon O&#39;Hanlon
Simon O&#39;Hanlon

Reputation: 59970

This might make your life a bit easier...

out <- lapply( data.frame( t(test) ) , matrix , ncol = 3 , byrow = TRUE )
res <- do.call( cbind , out )
    [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12]
 [1,]    1    2    3   31   32   33   61   62   63    91    92    93
 [2,]    4    5    6   34   35   36   64   65   66    94    95    96
 [3,]    7    8    9   37   38   39   67   68   69    97    98    99
 [4,]   10   11   12   40   41   42   70   71   72   100   101   102
 [5,]   13   14   15   43   44   45   73   74   75   103   104   105
 [6,]   16   17   18   46   47   48   76   77   78   106   107   108
 [7,]   19   20   21   49   50   51   79   80   81   109   110   111
 [8,]   22   23   24   52   53   54   82   83   84   112   113   114
 [9,]   25   26   27   55   56   57   85   86   87   115   116   117
[10,]   28   29   30   58   59   60   88   89   90   118   119   120

Possibly even slightly easier would be to do...

do.call( cbind , lapply( 1:4 , function(x) matrix( test[x,] , ncol = 3 , byrow = F ) ) )

If you insist on using a for loop this is probably the easiest way...

out <- numeric()
for( i in 1:4 ){
  tmp <- matrix( test[ i , ] , ncol = 3 , byrow = TRUE )
  out <- cbind( out , tmp )
  }

The problem stemmed from your use of out <- data.frame to initialise the result data structure. It meant you were trying to cbind a data.frame with no rows to one with 10 rows. Not possible (although intuitively being able to cbind an empty vector with a 10 row matrix should probably fail too but it doesnt!).

Upvotes: 4

Related Questions