r - 在 R 中嵌入 data.frames 的嵌套列表

标签 r dplyr tidyr jsonlite

设置:

我有一个 tibble(命名数据),其中嵌入了 data.frames 列表。

df1 <- data.frame(name = c("columnName1","columnName2","columnName3"),
                  value = c("yes", 1L, 0L),
                  stringsAsFactors = F)

df2 <- data.frame(name = c("columnName1","columnName2","columnName3"),
                  value = c("no", 1L, 1L),
                  stringsAsFactors = F)

df3 <- data.frame(name = c("columnName1","columnName2","columnName3"),
                  value = c("yes", 0L, 0L),
                  stringsAsFactors = F)

responses = list(df1,
                 df2,
                 df3)

data <- tibble(ids = c(23L, 42L, 84L),
               responses = responses)

请注意,这是数据的简化示例。原始数据来自平面 json 文件并使用 jsonlite::stream_in() 函数加载。

目标:

我的目标是将此 tibble 转换为另一个 tibble,其中嵌入的 data.frames 作为列展开(转置);例如,我的目标标题是:

goal <- tibble(ids = c(23L, 42L, 84L),
               columnName1 = c("yes","no","yes"),
               columnName2 = c(1L, 1L, 0L),
               columnName3 = c(0L, 1L, 0L))

# goal tibble
> goal
# A tibble: 3 x 4
    ids columnName1 columnName2 columnName3
  <int> <chr>             <int>       <int>
1    23 yes                   1           0
2    42 no                    1           1
3    84 yes                   0           0

我的不优雅的解决方案:

使用dplyr::bind_rows()tidyr::spread():

rdf <- dplyr::bind_rows(data$responses, .id = "id") %>%
  tidyr::spread(key = "name", -id)

goal2 <- cbind(ids = data$ids, rdf[,-1]) %>%
  as.tibble()

将我的解决方案与目标进行比较:

# produced tibble
> goal2
# A tibble: 3 x 4
    ids columnName1 columnName2 columnName3
* <int> <chr>       <chr>       <chr>      
1    23 yes         1           0          
2    42 no          1           1          
3    84 yes         0           0          

总的来说,我的解决方案有效,但存在一些问题:

  1. 我不知道如何通过 bind_rows() 传递唯一 id,这迫使我创建一个无法与原始 id 匹配的虚拟 id(“id”) (“id”)。这迫使我使用 cbind() (我不喜欢)并手动删除虚拟 ID(在 rdf 上使用 -1 切片)。

  2. 当我的方法将整数列转换为字符时,列的格式丢失了。

关于如何改进我的解决方案有什么建议(特别是使用基于 tidyverse 的包,如 tidyjson 或 tidyr)?

最佳答案

我们可以使用map循环“responses”列,使用convert = TRUE将其spread到“wide”,以便该列类型,使用 transmute 将其创建为列,然后使用 unnest

library(tidyverse)
data %>% 
     transmute(ids, ind = map(responses, ~.x %>% 
                                  spread(name, value, convert = TRUE)))  %>%
     unnest
# A tibble: 3 x 4
#    ids columnName1 columnName2 columnName3
#   <int> <chr>             <int>       <int>
#1    23 yes                   1           0
#2    42 no                    1           1
#3    84 yes                   0           0

或者使用OP的代码,我们使用“ids”列设置list的名称,执行bind_rows,然后spread

bind_rows(setNames(data$responses, data$ids), .id = 'ids') %>% 
            spread(name, value, convert = TRUE)

关于r - 在 R 中嵌入 data.frames 的嵌套列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48139451/

相关文章:

r - 矢量化 str_locate 未按预期工作

R:tidyr::spread 的编程替代方案?

r - 如何在 R 中的 "for loop"循环中转换 "foreach"?

r - 通过分隔符解析文本文件并使用R输出多个文件

r - 使用 sapply 的列表和矩阵

r - 使用行索引号来计算值

r - 子组内的 dplyr 计数

r - 如何在ggplot中绘制多条线段

r - separate() 在 tidyr 中与 NA

r - "Error in UseMethod("mutate ") : no applicable method for ' mutate ' applied to an object of class "function"尝试分隔列时