将列表列表强制转换为data_frame,但在列表列中维护* some *元素

时间:2018-04-06 22:04:21

标签: r tibble

我正在寻找一种方法,可以将列表结构可靠地强制转换为data.frametibble,同时将一列或多列保留为列列。请考虑以下列表结构:

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))

这不按预期工作:

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

因为"模型中的lm对象"列在转换中得到矢量化。但是,在list中包装模型会得到预期的结果:

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

不幸的是,我有一个用例,我事先并不知道给定列是否是列表。我正在使用一个输出类似这样的函数:

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()

有没有办法阻止data_frame将转换中的对象矢量化为tibble?如果没有,我可以使用哪种替代方法?

2 个答案:

答案 0 :(得分:2)

以下是final

的一个选项
tidyverse

对于第一种情况,请制作&#39;模型&#39;作为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> ,然后使用list

as_tibble

答案 1 :(得分:0)

我不满意的一个选项,但可能有助于指导讨论: 检查列表结构中每个元素的类型,如果它们是非原子的或具有多个元素,则将它们包装在列表中:

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()

不确定这是多么强大,也可能很慢。

编辑

我在old dplyr issue链接的related tibble issue中找到的另一个选项:

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

然而,这仅适用于一个&#34;列&#34;一次,并且还要求您知道要在列表中包装的列的名称。

如果实施as_tibble_row,那可能是首选解决方案。