denormalize / coerce list(带嵌套向量)到R中的data.frame

时间:2017-11-11 20:56:24

标签: r purrr

我正在阅读像

这样的yaml文件
- person_id: 111
  person_name: Russell
  time:
  - 1
  - 2
  - 3
  value:
  - a
  - b
  - c
- person_id: 222
  person_name: Steven
  time:
  - 1
  - 2
  value:
  - d
  - e

我想反规范化为:

  person_id person_name time value
1       111     Russell    1     a
2       111     Russell    2     b
3       111     Russell    3     c
4       222      Steven    1     d
5       222      Steven    2     e

我有一个解决方案,但我希望有更简洁的东西。这是嵌套列表:

l <- list(
  list( 
    person_id   = 111L,
    person_name = "Russell", 
    time        = 1:3, 
    value       = letters[1:3]
  ),
  list( 
    person_id   = 222L,
    person_name = "Steven", 
    time        = 1:2, 
    value       = letters[4:5]
  )
)   

关于可能的重复,此问题类似于(1)How to denormalize nested list in R?,但结构不同(round / diff / saldo结构与time / value此处)和(2)Split comma-separated column into separate rows,但time是矢量,而不是像director这样的逗号分隔元素。我希望这种不同的结构有所帮助。

4 个答案:

答案 0 :(得分:1)

Reduce(rbind,lapply(l,data.frame))

答案 1 :(得分:1)

赞美@lmo和@submartingale的想法/方法,这里是一个purrr / tidyverse版本,它将每个嵌套的列表转换为data.frame / tibble(通过复制name&amp; id的父元素),然后将它们堆叠成单个tibble。

l %>% 
  purrr::map_df(tibble::as_tibble)

感谢各位提出如此简明扼要的内容。

答案 2 :(得分:1)

一个简单的基本R方法是使用lapplydata.frame返回data.frames列表,然后使用do.callrbind来合并data.frames到一个data.frame对象。

do.call(rbind, lapply(l, data.frame))

返回

  person_id person_name time value
1       111     Russell    1     a
2       111     Russell    2     b
3       111     Russell    3     c
4       222      Steven    1     d
5       222      Steven    2     e

请注意,person_name和value将是因子向量,这可能很烦人。如果需要,可以使用stringsAsFactors参数将这些转换为字符向量。

do.call(rbind, lapply(l, data.frame, stringsAsFactors=FALSE))

打印输出看起来相同,但这两个变量的基础数据类型已经改变。

答案 3 :(得分:0)

这很有效,但不太理想,因为(a)新data.frame中的每个向量都需要处理,(b)每个向量的类型是显式的(例如,{{ 1}} vs purrr:map_chr

purrr:map_int