2

I have nested list as follows,

 dput( list(structure(c("123.60", " on"))))

I am interested in converting the elements in this nested list into a dataframe. For example, the output should be as follows.

      code      description      
      123.60    not stated as uncontrolled, with neurological manifestations
      123.50    not stated as uncontrolled, with ophthalmic manifestations
      .
      .
      .
      123.52    uncontrolled, with ophthalmic manifestations 

Need help converting these elements into a dataframe.

shadow
  • 21,823
  • 4
  • 63
  • 77
Science11
  • 788
  • 1
  • 8
  • 24

1 Answers1

6

That's not exactly a nested list, but a list of named character vectors. You can apply as.data.frame.list to each element, then use rbind. So if x is your list, then

df <- do.call(rbind, lapply(x, as.data.frame.list, stringsAsFactors = FALSE))
## below is optional - converts character columns to appropriate type
## but will also convert some columns back to factors again
df[] <- lapply(df, type.convert) 
df
#      code                                                   description codeSystem codeSystemVersion
# 1  123.60  not stated as uncontrolled, with neurological manifestations     XAZ9CM       XAZ9CM-2012
# 2  123.50    not stated as uncontrolled, with ophthalmic manifestations     XAZ9CM       XAZ9CM-2012
# 3  123.61  not stated as uncontrolled, with neurological manifestations     XAZ9CM       XAZ9CM-2012
# 4   123.7                              peripheral circulatory disorders     XAZ9CM       XAZ9CM-2012
# 5  123.40         not stated as uncontrolled, with renal manifestations     XAZ9CM       XAZ9CM-2012
# 6  123.41         not stated as uncontrolled, with renal manifestations     XAZ9CM       XAZ9CM-2012
# 7   123.5                                     ophthalmic manifestations     XAZ9CM       XAZ9CM-2012
# 8  123.53                  uncontrolled, with ophthalmic manifestations     XAZ9CM       XAZ9CM-2012
# 9  123.52                  uncontrolled, with ophthalmic manifestations     XAZ9CM       XAZ9CM-2012
# 10  123.4                                          renal manifestations     XAZ9CM       XAZ9CM-2012

Update : You can also do

data.frame(do.call(rbind, x), stringsAsFactors=FALSE)

And other, likely more efficient, possibilities include

library(data.table)
rbindlist(lapply(x, as.list))

and

library(dplyr)
bind_rows(lapply(x, as.data.frame.list, stringsAsFactors=FALSE))

and (thanks to Ananda Mahto)

library(stringi)
data.frame(stri_list2matrix(x, byrow=TRUE), stringsAsFactors=FALSE)

All of these would still require a type conversion on the first column if you wish for it to be numeric.

Also, the data from this question seems to have disappeared, so here it is, copied from the edit history.

 x <- list(structure(c("123.60", " not stated as uncontrolled, with neurological manifestations",                 
     "XAZ9CM", "XAZ9CM-2012"), .Names = c("code", "description", "codeSystem",                                    
     "codeSystemVersion")), structure(c("123.50", " not stated as uncontrolled, with ophthalmic manifestations",  
     "XAZ9CM", "XAZ9CM-2012"), .Names = c("code", "description", "codeSystem",                                    
     "codeSystemVersion")), structure(c("123.61", "not stated as uncontrolled, with neurological manifestations", 
     "XAZ9CM", "XAZ9CM-2012"), .Names = c("code", "description", "codeSystem",                                    
     "codeSystemVersion")), structure(c("123.7", "peripheral circulatory disorders",                              
     "XAZ9CM", "XAZ9CM-2012"), .Names = c("code", "description", "codeSystem",                                    
     "codeSystemVersion")), structure(c("123.40", " not stated as uncontrolled, with renal manifestations",       
     "XAZ9CM", "XAZ9CM-2012"), .Names = c("code", "description", "codeSystem",                                    
     "codeSystemVersion")), structure(c("123.41", " not stated as uncontrolled, with renal manifestations",       
     "XAZ9CM", "XAZ9CM-2012"), .Names = c("code", "description", "codeSystem",                                    
     "codeSystemVersion")), structure(c("123.5", "ophthalmic manifestations",                                     
     "XAZ9CM", "XAZ9CM-2012"), .Names = c("code", "description", "codeSystem",                                    
     "codeSystemVersion")), structure(c("123.53", "uncontrolled, with ophthalmic manifestations",                 
     "XAZ9CM", "XAZ9CM-2012"), .Names = c("code", "description", "codeSystem",                                    
     "codeSystemVersion")), structure(c("123.52", " uncontrolled, with ophthalmic manifestations",                
     "XAZ9CM", "XAZ9CM-2012"), .Names = c("code", "description", "codeSystem",                                    
     "codeSystemVersion")), structure(c("123.4", "renal manifestations",                                          
     "XAZ9CM", "XAZ9CM-2012"), .Names = c("code", "description", "codeSystem",                                    
     "codeSystemVersion")))   
Rich Scriven
  • 97,041
  • 11
  • 181
  • 245
  • 1
    @Science11 - good! I added `type.convert` to make sure numeric columns end up numerics, and not characters – Rich Scriven Jan 13 '15 at 21:00
  • 1
    Never heard of `type.convert` before... – David Arenburg Jan 13 '15 at 21:06
  • 1
    @DavidArenburg - It's pretty neat. It attempts conversion on character vectors to their appropriate types. Actually now that I think about it, it might not be appropriate here because it just converted the strings back to factors again. Haha – Rich Scriven Jan 13 '15 at 21:07
  • Yeah thanks, I know how to read documentation :) Where did you find this gem? – David Arenburg Jan 13 '15 at 21:09
  • 1
    @DavidArenburg - Actually I first saw it in Ananda Mahto's code – Rich Scriven Jan 13 '15 at 21:12
  • @DavidArenburg, and I found it when reading the help file for `read.table` one day. Richard, +1, but where did this sample data come from? (And why didn't you share it so others can play with the answer too?) – A5C1D2H2I1M1N2O1R2T1 Jan 14 '15 at 06:02
  • @AnandaMahto - I never noticed that OP changed it. Hopefully it's in the edit history – Rich Scriven Jan 14 '15 at 06:06
  • @AnandaMahto Yes, I wasn't sure whether it is better to run `as.data.frame.list` first or `data.frame` after `do.call(rbind, x)`. Both are probably expensive on large data – Rich Scriven Jan 14 '15 at 06:18
  • @AnandaMahto - not sure if you were going to post the `stringi` method. I added it but if you want to post it I'll remove it – Rich Scriven Jan 14 '15 at 06:34