0

I am wondering how I can convert a list with both numeric and string variables to a dataframe:

For example:

aa<-c("a","b","b","b","d")
bb<-c("Yes","No","No","Yes","Yes")
cc<-c(1,2,4,4,3)

x<-list(aa=aa,bb=bb,cc=cc)

How can I convert x to a dataframe, such that when I call x I get:

  aa  bb cc
1  a Yes  1
2  b  No  2
3  b  No  4
4  b Yes  4
5  d Yes  3

Thanks!

Head and toes
  • 659
  • 3
  • 11
  • 29

4 Answers4

3

With large data in a list, it's recommended to change the data "in place".

For reference, see Simon Urbanek's answer here: Quickly reading very large tables as dataframes in R

attr(x, "row.names") <- .set_row_names(unique(lengths(x)))
class(x) <- "data.frame"
x
#   aa  bb cc
# 1  a Yes  1
# 2  b  No  2
# 3  b  No  4
# 4  b Yes  4
# 5  d Yes  3

This has two major advantages over as.data.frame One is that it avoids copying the object x. The other is that it keeps the column classes in line with the list classes (see the following). With as.data.frame, character classes would be converted to factors.

sapply(x, class)
#          aa          bb          cc 
# "character" "character"   "numeric" 
Community
  • 1
  • 1
Rich Scriven
  • 97,041
  • 11
  • 181
  • 245
  • Can you always just assign a class like that? That's really nice. – Elin Aug 24 '14 at 16:08
  • 1
    If you mean with `class(x) <- ...`, yes. Although it's a bit more technical than that (with `attributes` and things). `?class` has some good info on it. I know that this works really well with lists. – Rich Scriven Aug 24 '14 at 16:11
1

A data.table would also have a class of data.frame, so you can make use of the efficient setDT function:

x <- list(aa = aa, bb = bb, cc = cc)

library(data.table)
setDT(x)
is.data.frame(x)
# [1] TRUE
str(x)
# Classes ‘data.table’ and 'data.frame':    5 obs. of  3 variables:
#  $ aa: chr  "a" "b" "b" "b" ...
#  $ bb: chr  "Yes" "No" "No" "Yes" ...
#  $ cc: num  1 2 4 4 3
#  - attr(*, ".internal.selfref")=<externalptr> 
A5C1D2H2I1M1N2O1R2T1
  • 190,393
  • 28
  • 405
  • 485
0

You can do x<-as.data.frame(x).

Updated based on @Frank's good below, if you want to avoid converting characters to factors do

x<-as.data.frame(x, StringsAsFactors = FALSE).

Elin
  • 6,507
  • 3
  • 25
  • 47
  • 1
    Just a note about column classes. The above solution will convert the character vectors to factor, by default. A way to prevent this, is to use `stringsAsFactors = FALSE` like so `data.frame(x, stringsAsFactors = FALSE)`. – Jota Aug 24 '14 at 15:07
0
> x = data.frame(aa,bb,cc)
> x
  aa  bb cc
1  a Yes  1
2  b  No  2
3  b  No  4
4  b Yes  4
5  d Yes  3
> 
> str(x)
'data.frame':   5 obs. of  3 variables:
 $ aa: Factor w/ 3 levels "a","b","d": 1 2 2 2 3
 $ bb: Factor w/ 2 levels "No","Yes": 2 1 1 2 2
 $ cc: num  1 2 4 4 3
> 

or:

> x = data.frame(aa,bb,cc, stringsAsFactors=F)
> x
  aa  bb cc
1  a Yes  1
2  b  No  2
3  b  No  4
4  b Yes  4
5  d Yes  3
> str(x)
'data.frame':   5 obs. of  3 variables:
 $ aa: chr  "a" "b" "b" "b" ...
 $ bb: chr  "Yes" "No" "No" "Yes" ...
 $ cc: num  1 2 4 4 3
> 
rnso
  • 23,686
  • 25
  • 112
  • 234