从 R 中的数据框列中提取具有不对称内容的 JSON 数据
Extracting JSON data with asymetric content from a dataframe column in R
我从数据库中加载了一个 table,该数据库包含一列,每一行都有 JSON 数据。
table 类似于下面的示例。 (由于列数据的格式,我无法复制我拥有的 data.frame)
dataframe_example <- data.frame(id = c(1,2,3),
name = c("name1","name2","name3"),
JSON_col = c({"_inv": [10,20,30,40]}, "_person": ["_personid": "green"],
{"_inv": [15,22]}, "_person": ["_personid": "blue"],
{"_inv": []}, "_person": ["_personid": "red"]))
我有以下两个问题:
一些项目(例如“_inv”)有时有完整的 4 个数字条目,有时更少,有时什么都没有。其他一些项目(例如“_person”)通常包含另一个 header,但只有一个字符数据点。
我的目标是保留现有的数据帧列(例如 id 和名称)并将数据分散在 json 列中,这样我就有了包含每个信息点的新列。目标数据框看起来有点像这样:
data.frame(id = c(1,2,3),
name = c("name1","name2","name3"),
`_inv_1` = c(10,15,NA),
`_inv_2` = c(20,22,NA),
`_inv_3` = c(30,NA,NA),
`_inv_4` = c(40,NA,NA),
`_person_id` = c("green","blue","red"))
请记住,我处理 JSON 数据的经验很少,也没有处理不均匀 JSON 数据的经验。
使用 purrr
我得到:
frame <- purrr::map(dataframe_example$JSON_col, jsonlite::fromJSON)
这给了我一个包含 n 个元素的大列表,其中 n 是原始数据帧的长度。 “名称”项包含 n 个列表 [[1]],每个列表都有自己的类型 object,范围从 double 到 data.frame。双 object 包含四个数字观察值(例如 _inv),一些 object 本身就是列表(例如 _person),其中进一步包含“_personid”,然后是一个条目。数据框包含 JSON 数据中每个观测值的日期时间戳。 (每个 _inv 项目都有一个时间戳)
有没有办法通过从我的“框架”object 中提取数据或完全不同的解决方案来获得上述解决方案?
library(tidyverse)
library(jsonlite)
#>
#> Attaching package: 'jsonlite'
#> The following object is masked from 'package:purrr':
#>
#> flatten
dataframe_example <-
data.frame(
id = c(1, 2, 3),
name = c("name1", "name2", "name3"),
JSON_col = c(
"{\"_inv\": [10,20,30,40], \"_person\": {\"_personid\": \"green\"}}",
"{\"_inv\": [15,22], \"_person\": {\"_personid\": \"blue\"}}",
"{\"_inv\": [], \"_person\": {\"_personid\": \"red\"}}"
)
)
dataframe_example %>%
as_tibble() %>%
mutate(
JSON_col = JSON_col %>% map(parse_json)
) %>%
unnest_wider(JSON_col) %>%
unnest(`_inv`) %>%
unnest(`_inv`) %>%
unnest(`_person`) %>%
unnest(`_person`) %>%
group_by(id, name) %>%
mutate(inv_id = row_number()) %>%
pivot_wider(names_from = inv_id, values_from = `_inv`, names_prefix = "_inv_")
#> # A tibble: 2 x 7
#> # Groups: id, name [2]
#> id name `_person` `_inv_1` `_inv_2` `_inv_3` `_inv_4`
#> <dbl> <chr> <chr> <int> <int> <int> <int>
#> 1 1 name1 green 10 20 30 40
#> 2 2 name2 blue 15 22 NA NA
由 reprex package (v2.0.1)
于 2021-11-25 创建
我从数据库中加载了一个 table,该数据库包含一列,每一行都有 JSON 数据。 table 类似于下面的示例。 (由于列数据的格式,我无法复制我拥有的 data.frame)
dataframe_example <- data.frame(id = c(1,2,3),
name = c("name1","name2","name3"),
JSON_col = c({"_inv": [10,20,30,40]}, "_person": ["_personid": "green"],
{"_inv": [15,22]}, "_person": ["_personid": "blue"],
{"_inv": []}, "_person": ["_personid": "red"]))
我有以下两个问题: 一些项目(例如“_inv”)有时有完整的 4 个数字条目,有时更少,有时什么都没有。其他一些项目(例如“_person”)通常包含另一个 header,但只有一个字符数据点。
我的目标是保留现有的数据帧列(例如 id 和名称)并将数据分散在 json 列中,这样我就有了包含每个信息点的新列。目标数据框看起来有点像这样:
data.frame(id = c(1,2,3),
name = c("name1","name2","name3"),
`_inv_1` = c(10,15,NA),
`_inv_2` = c(20,22,NA),
`_inv_3` = c(30,NA,NA),
`_inv_4` = c(40,NA,NA),
`_person_id` = c("green","blue","red"))
请记住,我处理 JSON 数据的经验很少,也没有处理不均匀 JSON 数据的经验。
使用 purrr
我得到:
frame <- purrr::map(dataframe_example$JSON_col, jsonlite::fromJSON)
这给了我一个包含 n 个元素的大列表,其中 n 是原始数据帧的长度。 “名称”项包含 n 个列表 [[1]],每个列表都有自己的类型 object,范围从 double 到 data.frame。双 object 包含四个数字观察值(例如 _inv),一些 object 本身就是列表(例如 _person),其中进一步包含“_personid”,然后是一个条目。数据框包含 JSON 数据中每个观测值的日期时间戳。 (每个 _inv 项目都有一个时间戳)
有没有办法通过从我的“框架”object 中提取数据或完全不同的解决方案来获得上述解决方案?
library(tidyverse)
library(jsonlite)
#>
#> Attaching package: 'jsonlite'
#> The following object is masked from 'package:purrr':
#>
#> flatten
dataframe_example <-
data.frame(
id = c(1, 2, 3),
name = c("name1", "name2", "name3"),
JSON_col = c(
"{\"_inv\": [10,20,30,40], \"_person\": {\"_personid\": \"green\"}}",
"{\"_inv\": [15,22], \"_person\": {\"_personid\": \"blue\"}}",
"{\"_inv\": [], \"_person\": {\"_personid\": \"red\"}}"
)
)
dataframe_example %>%
as_tibble() %>%
mutate(
JSON_col = JSON_col %>% map(parse_json)
) %>%
unnest_wider(JSON_col) %>%
unnest(`_inv`) %>%
unnest(`_inv`) %>%
unnest(`_person`) %>%
unnest(`_person`) %>%
group_by(id, name) %>%
mutate(inv_id = row_number()) %>%
pivot_wider(names_from = inv_id, values_from = `_inv`, names_prefix = "_inv_")
#> # A tibble: 2 x 7
#> # Groups: id, name [2]
#> id name `_person` `_inv_1` `_inv_2` `_inv_3` `_inv_4`
#> <dbl> <chr> <chr> <int> <int> <int> <int>
#> 1 1 name1 green 10 20 30 40
#> 2 2 name2 blue 15 22 NA NA
由 reprex package (v2.0.1)
于 2021-11-25 创建