R:将数据框列中的嵌套JSON转换为同一数据框中的附加列

时间:2018-04-03 15:27:18

标签: r json dataframe nested

我有一个数据框,其中包含一些非常混乱的JSON数据列。我想将该列中的JSON条目转换为同一数据框中的其他列,我有一个混乱的解决方案,但将它应用于我的实际数据集将会很繁琐冗长。

以下是我的示例数据框:

sample.df <- data.frame(id = c(101, 102, 103, 104),
                    json_col = c('[{"foo_a":"bar"}]',
                                 '[{"foo_a":"bar","foo_b":"bar"}]',
                                 '[{"foo_a":"bar","foo_c":2}]',
                                 '[{"foo_a":"bar","foo_b":"bar","foo_c":2,"nested_col":{"foo_d":"bar","foo_e":3}}]'),
                    startdate = as.Date(c('2010-11-1','2008-3-25','2007-3-14','2006-2-21')))

实际上我的数据框有超过100000个条目,由多个JSON列组成,我需要将解决方案应用于这个问题,还有几个嵌套列表顺序(即嵌套列表中的嵌套列表)。

这是我的解决方案:

j.col <- sample.df[2]
library(jsonlite)
j.l <- apply(j.col, 1, jsonlite::fromJSON, flatten = T)
library(dplyr)
l.as.df <- bind_rows(lapply(j.l,data.frame))
new.df <- cbind(sample.df$id, l.as.df, sample.df$startdate)

我的解决方案是一种迂回方法,我使用JSON东西从数据框中提取列,然后将JSON转换为第二个数据帧,然后我将两个数据帧合并到第三个数据帧中。对我的实际数据来说,这将是漫长而乏味的,更不用说它是不优雅的。如何在不创建其他数据框的情况下执行此操作?

提前感谢您的帮助!

3 个答案:

答案 0 :(得分:2)

library(dplyr)
library(tidyr)
library(purrr)
library(jsonlite)

sample.df %>%
  mutate(
    json_parsed = map(json_col, ~ fromJSON(., flatten=TRUE))
  ) %>%
  unnest(json_parsed)

#    id
# 1 101
# 2 102
# 3 103
# 4 104
#                                                                           json_col
# 1                                                                [{"foo_a":"bar"}]
# 2                                                  [{"foo_a":"bar","foo_b":"bar"}]
# 3                                                      [{"foo_a":"bar","foo_c":2}]
# 4 [{"foo_a":"bar","foo_b":"bar","foo_c":2,"nested_col":{"foo_d":"bar","foo_e":3}}]
#    startdate foo_a foo_b foo_c nested_col.foo_d nested_col.foo_e
# 1 2010-11-01   bar  <NA>    NA             <NA>               NA
# 2 2008-03-25   bar   bar    NA             <NA>               NA
# 3 2007-03-14   bar  <NA>     2             <NA>               NA
# 4 2006-02-21   bar   bar     2              bar                3

如果要减少库,可以删除purrr,而不是使用:

...
    json_parsed = lapply(.$json_col, fromJSON, flatten=TRUE)
...

答案 1 :(得分:1)

我认为这会奏效。主要思想是我们将json_col转换为字符串,然后我们可以将其传递给负责其余部分的fromJSON函数。

library(stringi)
library(jsonlite)

sample.df$json_col<- as.character(sample.df$json_col)
json_obj<- paste(sample.df$json_col, collapse = "")
json_obj<- stri_replace_all_fixed(json_obj, "][", ",")
new.df<- cbind(sample.df$id, fromJSON(json_obj), sample.df$startdate)

> new.df
#  sample.df$id foo_a foo_b foo_c nested_col.foo_d nested_col.foo_e
#1          101     _  <NA>    NA             <NA>               NA
#2          102     _     _    NA             <NA>               NA
#3          103     _  <NA>     2             <NA>               NA
#4          104     _     _     2                _                3
#  sample.df$startdate
#1          2010-11-01
#2          2008-03-25
#3          2007-03-14
#4          2006-02-21

确保cbind部分正常工作!在这种情况下,确实如此,但要确保在整体操作中,不要改变事物的顺序。

答案 2 :(得分:1)

这是另一种可以省去中间数据帧的方法:

library(dplyr)
library(jsonlite)

new.df <- sample.df %>% 
          rowwise() %>%
          do(data.frame(fromJSON(.$json_col, flatten = T))) %>%
          ungroup() %>%
          bind_cols(sample.df %>% select(-json_col))

print(new.df)
# # A tibble: 4 x 7
#   foo_a foo_b foo_c nested_col.foo_d nested_col.foo_e    id  startdate
#   <chr> <chr> <int>            <chr>            <int> <dbl>     <date>
# 1     _  <NA>    NA             <NA>               NA   101 2010-11-01
# 2     _     _    NA             <NA>               NA   102 2008-03-25
# 3     _  <NA>     2             <NA>               NA   103 2007-03-14
# 4     _     _     2                _                3   104 2006-02-21