Here you will find a solution that allows you to take advantage of previous knowledge of data field names and classes. In addition, avoiding repeated calls to as.data.frame and a single call to plyr rbind.fill() (as a rbind.fill() time), it works about 60 times faster according to your example data.
cols <- c("id", "ls", "ts", "l.lo","l.tz", "lt", "l.ac", "l.la", "l.pr", "m") numcols <- c("l.lo", "lt", "l.ac", "l.la") ## Flatten each top-level list element, converting it to a character vector. x <- lapply(obj$data, unlist) ## Extract fields that might be present in each record (returning NA if absent). y <- sapply(x, function(X) X[cols]) ## Convert to a data.frame with columns of desired classes. z <- as.data.frame(t(y), stringsAsFactors=FALSE) z[numcols] <- lapply(numcols, function(X) as.numeric(as.character(z[[X]])))
Edit: To confirm that my approach yields results identical to those in the original question, I performed the following test. (Note that in both cases I set stringsAsFactors=FALSE to avoid meaningless differences in factor level orders.)
flatdata <- lapply(obj$data, as.data.frame, stringsAsFactors=FALSE) mydf <- rbind.fill(flatdata) identical(z, mydf) # [1] TRUE
Further editing:
For the record only, here is an alternative version above that is additionally automatically:
- finds the names of all data fields
- defines their class / type
- forces the columns of the final data.frame file with the correct class
.
dat <- obj$data ## Find the names and classes of all fields fields <- unlist(lapply(xx, function(X) rapply(X, class, how="unlist"))) fields <- fields[unique(names(fields))] cols <- names(fields) ## Flatten each top-level list element, converting it to a character vector. x <- lapply(dat, unlist) ## Extract fields that might be present in each record (returning NA if absent). y <- sapply(x, function(X) X[cols]) ## Convert to a data.frame with columns of desired classes. z <- as.data.frame(t(y), stringsAsFactors=FALSE) ## Coerce columns of z (all currently character) back to their original type z[] <- lapply(seq_along(fields), function(i) as(z[[cols[i]]], fields[i]))