Create a data.frame where a column is a list
Slightly obscurely, from ?data.frame
:
If a list or data frame or matrix is passed to ‘data.frame’ it is as if each component or column had been passed as a separate argument (except for matrices of class ‘"model.matrix"’ and those protected by ‘I’).
(emphasis added).
So
data.frame(a=1:3,b=I(list(1,1:2,1:3)))
seems to work.
data_frame
s (variously called tibbles
, tbl_df
, tbl
) natively support the creation of list columns using the data_frame
constructor. To use them, load one of the many libraries with them such as tibble
, dplyr
or tidyverse
.
> data_frame(abc = letters[1:3], lst = list(1:3, 1:3, 1:3))
# A tibble: 3 × 2
abc lst
<chr> <list>
1 a <int [3]>
2 b <int [3]>
3 c <int [3]>
They are actually data.frames
under the hood, but somewhat modified. They can almost always be used as normal data.frames
. The only exception I've found is that when people do inappropriate class checks, they cause problems:
> #no problem
> data.frame(x = 1:3, y = 1:3) %>% class
[1] "data.frame"
> data.frame(x = 1:3, y = 1:3) %>% class == "data.frame"
[1] TRUE
> #uh oh
> data_frame(x = 1:3, y = 1:3) %>% class
[1] "tbl_df" "tbl" "data.frame"
> data_frame(x = 1:3, y = 1:3) %>% class == "data.frame"
[1] FALSE FALSE TRUE
> #dont use if with improper testing!
> if(data_frame(x = 1:3, y = 1:3) %>% class == "data.frame") "something"
Warning message:
In if (data_frame(x = 1:3, y = 1:3) %>% class == "data.frame") "something" :
the condition has length > 1 and only the first element will be used
> #proper
> data_frame(x = 1:3, y = 1:3) %>% inherits("data.frame")
[1] TRUE
I recommending reading about them in R 4 Data Science (free).
If you are working with data.tables
, then you can avoid the call to I()
library(data.table)
# the following works as intended
data.table(a=1:3,b=list(1,1:2,1:3))
a b
1: 1 1
2: 2 1,2
3: 3 1,2,3
You can use list2DF
to create a data.frame
where a column is a list
.
x <- list2DF(list(a=1:3, b=list(1:1, 1:2, 1:3)))
#x <- data.frame(a=1:3, list2DF(list(b=list(1:1, 1:2, 1:3)))) #Alternative
x
# a b
#1 1 1
#2 2 1, 2
#3 3 1, 2, 3
str(x)
#'data.frame': 3 obs. of 2 variables:
# $ a: int 1 2 3
# $ b:List of 3
# ..$ : int 1
# ..$ : int 1 2
# ..$ : int 1 2 3
With this you don't have the attr
AsIs
in the data.frame
, what you would have when using I
.