Assigning results of a for loop to an empty matrix

30,428

Solution 1

Your property function is returning a list. If you want to store the numbers in a matrix, you should have it return a numeric vector:

property <- function(mat)
{
  ....
  c(a, b, c, d, e)  # probably a good idea to rename your "c" variable
}

Alternatively, instead of defining obj to be a matrix, make it a data.frame (which conceptually makes more sense, as each column represents a different quantity).

obj <- data.frame(a=0, b=0, c=0, ...)
for(i in 1:ncol(x))
  ....
  obj[j, ] <- property(temp)

Finally, note that your call to write.table will overwrite the contents of myfile.csv, so the only output it will contain is the result for the last iteration of i.

Solution 2

Use rbind:

 obj <- rbind(obj, prop)
Share:
30,428
Laura
Author by

Laura

Updated on August 09, 2020

Comments

  • Laura
    Laura over 3 years

    I have another question for the brilliant minds out there (this site is so addictive).

    I am running some simulations on a matrix and I have nested for loops for this purpose. The first creates a vector that increases by one each time a loop cycles. The nested loop is running simulations by randomizing the vector, attaching it to the matrix, and calculating some simple properties on the new matrix. (For an example, I used properties that will not vary in the simulations, but in practice I require the simulations to get a good idea of the impact of the randomized vector.) The nested loop runs 100 simulations, and ultimately I want only the column means of those simulations.

    Here's some example code:

    property<-function(mat){                       #where mat is a matrix
      a=sum(mat) 
      b=sum(colMeans(mat))
      c=mean(mat)
      d=sum(rowMeans(mat))
      e=nrow(mat)*ncol(mat)
      answer=list(a,b,c,d,e)
      return(answer)
      }
    
    x=matrix(c(1,0,1,0, 0,1,1,0, 0,0,0,1, 1,0,0,0, 1,0,0,1), byrow=T, nrow=5, ncol=4)
    
    obj=matrix(nrow=100,ncol=5,byrow=T)            #create an empty matrix to dump results into
    
    for(i in 1:ncol(x)){                           #nested for loops
      a=rep(1,times=i)                             #repeat 1 for 1:# columns in x
      b=rep(0,times=(ncol(x)-length(a)))           #have the rest of the vector be 0
      I.vec=append(a,b)                            #append these two for the I vector
        for (j in 1:100){
          I.vec2=sample(I.vec,replace=FALSE)       #randomize I vector
          temp=rbind(x,I.vec2)
          prop<-property(temp)
          obj[[j]]<-prop
          }
      write.table(colMeans(obj), 'myfile.csv', quote = FALSE, sep = ',', row.names = FALSE)
      }
    

    The problem I am encountering is how to fill in the empty object matrix with the results of the nested loop. obj ends up as a vector of mostly NAs, so it is clear that I am not assigning the results properly. I want each cycle to add a row of prop to obj, but if I try

    obj[j,]<-prop
    

    R tells me that there is an incorrect number of subscripts on the matrix.

    Thank you so much for your help!

    EDITS: Okay, so here is the improved code re the answers below:

    property<-function(mat){                       #where mat is a matrix
      a=sum(mat)
      b=sum(colMeans(mat))
      f=mean(mat)
      d=sum(rowMeans(mat))
      e=nrow(mat)*ncol(mat)
      answer=c(a,b,f,d,e)
      return(answer)
      }
    
    x=matrix(c(1,0,1,0, 0,1,1,0, 0,0,0,1, 1,0,0,0, 1,0,0,1), byrow=T, nrow=5, ncol=4)
    
    obj<-data.frame(a=0,b=0,f=0,d=0,e=0)            #create an empty dataframe to dump results into
    obj2<-data.frame(a=0,b=0,f=0,d=0,e=0)
    
    for(i in 1:ncol(x)){                           #nested for loops
      a=rep(1,times=i)                             #repeat 1 for 1:# columns in x
      b=rep(0,times=(ncol(x)-length(a)))           #have the rest of the vector be 0
      I.vec=append(a,b)                            #append these two for the I vector
        for (j in 1:100){
          I.vec2=sample(I.vec,replace=FALSE)       #randomize I vector
          temp=rbind(x,I.vec2)
          obj[j,]<-property(temp)
          }
      obj2[i,]<-colMeans(obj)
      write.table(obj2, 'myfile.csv', quote = FALSE,
      sep = ',', row.names = FALSE, col.names=F, append=T)
      }
    

    However, this is still glitchy, as the myfile should only have four rows (one for each column of x), but actually has 10 rows, with some repeated. Any ideas?

  • Laura
    Laura over 12 years
    Fantastic! Thank you for all of this advice.
  • Laura
    Laura over 12 years
    I can fix the overwrite problem by adding in "append=T". obj works properly now, but the file produced write.table was still only one column. I fixed this by creating a second empty dataframe with the colMeans of obj as rows and then wrote that to an csv file.