My data frame contains the output of a survey with a select multiple question type. Some cells have multiple values.
df <- data.frame(a=1:3,b=I(list(1,1:2,1:3)))
df
a b
1 1 1
2 2 1, 2
3 3 1, 2, 3
I would like to flatten out the list to obtain the following output:
df
a b
1 1 1
2 2 1
3 2 2
4 3 1
5 3 2
6 3 3
should be easy but somehow I can't find the search terms. thanks.
Here's one way, with
data.table
:If
b
is stored consistently,as.integer
can be skipped. You can check withHere's another base solution, far less elegant than any other solution posted thus far. Posting for the sake of completeness, though personally I would recommend akrun's base solution.
This constructs the first column as the elements of
a
, where each is repeated to match the length of the corresponding list item fromb
. The second column isb
"flattened" usingdo.call()
withc()
.As Ananda Mahto pointed out in a comment,
sapply(b, length)
can be replaced withlengths(b)
in the most recent version of R (3.2, if I'm not mistaken).You can just use
unnest
from "tidyr":Using
base R
, one option isstack
after naming thelist
elements of 'b' column with that of the elements of 'a'. We can usesetNames
to change the names.Or another option would be to use
unstack
to automatically name the list element of 'b' with 'a' elements and then do thestack
to get adata.frame
output.Or we can use a convenient function
listCol_l
fromsplitstackshape
to convert thelist
todata.frame
.