tags:

views:

274

answers:

3

I would like to construct a dataframe row-by-row in R. I've done some searching, and all I came up with is the suggestion to create an empty list, keep a list index scalar, then each time add to the list a single-row dataframe and advance the list index by one. Finally, do.call(rbind,) on the list.

While this works, it seems very cumbersome. Isn't there an easier way for achieving the same goal?

Obviously I refer to cases where I can't use some apply function and explicitly need to create the dataframe row by row. At least, is there a way to push into the end of a list instead of explicitly keeping track of the last index used?

+1  A: 

One can add rows to NULL:

df<-NULL;
while(...){
  #Some code that generates new row
  rbind(df,row)->df
}

for instance

df<-NULL
for(e in 1:10) rbind(df,data.frame(x=e,square=e^2,even=factor(e%%2==0)))->df
print(df)
mbq
How nice to be downvoted for giving accurate answer ;-)I agree that this is less efficient than Dirk's solution, still sometimes the time of programmer is more valuable than the than the time of CPU... or least error-prone approach is needed.
mbq
+1: it's not wrong. ;)
Stephen
+1  A: 

You can grow them row by row by appending or using rbind().

That does not mean you should. Dynamically growing structures is one of the least efficient ways to code in R.

If you can, just preserver all your data.frame up front:

N <- 1e4  # some magic number, possibly an overestimate

DF <- data.frame(num=rep(NA,10), txt=rep("", 10), # as many cols as you need
                 stringsAsFactors=FALSE)          # you don't know levels

and then during your operations insert row at a time

DF[i, ] <- c(1.4, "foo")

That should work for arbitrary data.frame and be much more efficient. If you overshot N you can always shrink empty rows out at the end.

Dirk Eddelbuettel
Didn't you mean to put N instead of 10, and list(1.4,"foo") instead of c(1.4,"foo") so as not to coerce the 1.4 into character mode?
Stephen
Yes, I meant to use N in the data.frame creation. Also, very good catch re the coercion into chat -- I had missed that.
Dirk Eddelbuettel
A: 

This is a silly example of how to use do.call(rbind,) on the output of Map() [which is similar to lapply()]

> DF <- do.call(rbind,Map(function(x) data.frame(a=x,b=x+1),x=1:3))
> DF
  x y
1 1 2
2 2 3
3 3 4
> class(DF)
[1] "data.frame"

I use this construct quite often.

Stephen