Coerce list of lists to data_frame, but maintain *some* elements in list columns

杀马特。学长 韩版系。学妹 提交于 2019-12-11 03:06:33

问题


I am looking for a way to reliably coerce a list structure to a data.frame or tibble while maintaining one or more columns as list columns. Consider the following list structure:

d = data.frame(x = 1:10, y = 1.5*(1:10) + rnorm(10))
ex = list(label = "A", number = 1L, model = lm(y ~ x, data = d))

This does not work as intended:

lapply(ex, as_data_frame) %>% bind_rows()

Because the lm object in the "model" column gets vectorized in the conversion. However, wrapping the model in list gets the expected result:

ex2 = list(label = "A", number = 1L, model = list(lm(y ~ x, data = d)))
as_data_frame(ex2)

Unfortunately, I have a use case where I don't know beforehand whether a given column is a list or not. I am working with a function that outputs something like this:

ex3 = list(
  list(label = "A", number = 1L, model = lm(y ~ x, data = d)),
  list(label = "B", number = 1L, model = lm(y ~ x + 0, data = d))
)
# won't work properly
lapply(ex3, as_data_frame) %>% bind_rows()

Is there a way to prevent data_frame from vectorizing an object in the transformation to a tibble? If not, what alternative approach could I use?


回答1:


Here is one option with tidyverse

library(tidyverse)
ex3 %>% 
 transpose %>% 
 map_if(~all(lengths(.) == 1), unlist) %>% 
 as_tibble
# A tibble: 2 x 3
#  label number model   
#   <chr>  <int> <list>  
#1 A          1 <S3: lm>
#2 B          1 <S3: lm>

For the first case, make the 'model' as a list and then use as_tibble

ex$model <- list(ex$model)
as_tibble(ex)



回答2:


One option that I'm not super happy with, but might help guide the discussion: Check the types of each element the list structure and wrap them in a list if they are non-atomic or have more than 1 element:

listify = function(x) {
  if(length(x) > 1L || !is.atomic(x))
    list(x)
  else
    x
}
lapply(ex3, function(x) as_data_frame(lapply(x, listify))) %>% bind_rows()

Not sure how robust this is, and probably slow too.


EDIT

Another option, which I found in an old dplyr issue linked from a related tibble issue:

library (purr)
ex3 = map(ex3, ~ as_list(extract(., "model"))

However, this only works on one "column" at a time, and also requires you to know the name of the column you want to wrap in a list.

If as_tibble_row gets implemented, that will probably be the preferred solution.



来源:https://stackoverflow.com/questions/49701573/coerce-list-of-lists-to-data-frame-but-maintain-some-elements-in-list-columns

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!