Assigning results of a for loop to an empty matrix
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)
Laura
Updated on August 09, 2020Comments
-
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 over 12 yearsFantastic! Thank you for all of this advice.
-
Laura over 12 yearsI 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.