我有一个数据框,其中包含一些非常混乱的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转换为第二个数据帧,然后我将两个数据帧合并到第三个数据帧中。对我的实际数据来说,这将是漫长而乏味的,更不用说它是不优雅的。如何在不创建其他数据框的情况下执行此操作?
提前感谢您的帮助!
答案 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