有没有办法从 JSON 列中有效地提取多个属性?
Is there a way to extract multiple attributes efficiently from a JSON column?
我有一个数据框,其中有一列包含 json 数据。我想从这个 json 数据中提取一些属性到数据框的命名列中。
示例数据
json_col = c('{"name":"john"}','{"name":"doe","points": 10}', '{"name":"jane", "points": 20}')
id = c(1,2,3)
df <- data.frame(id, json_col)
我能够使用
实现这个
library(tidyverse)
library(jsonlite)
extract_json_attr <- function(from, attr, default=NA) {
value <- from %>%
as.character() %>%
jsonlite::fromJSON(txt = .) %>%
.[attr]
return(ifelse(is.null(value[[1]]), default, value[[1]]))
}
df <- df %>%
rowwise() %>%
mutate(name = extract_json_attr(json_col, "name"),
points = extract_json_attr(json_col, "points", 0))
在这种情况下,extract_json_attr
需要为要提取的每个属性多次解析 json 列。
有没有更好的方法一次提取所有属性?
我尝试将此函数 return 多个值作为一个列表,但我无法将它与 mutate 一起使用来设置多个列。
extract_multiple <- function(from, attributes){
values <- from %>%
as.character() %>%
jsonlite::fromJSON(txt = .) %>%
.[attributes]
return (values)
}
我可以使用此函数提取所需的值
extract_multiple(df$json_col[1],c('name','points'))
extract_multiple(df$json_col[2],c('name','points'))
但不能将其应用于一次性设置多列。有没有更好的方法来有效地做到这一点?
这是使用 dplyr
中的 bind_rows
的一种方法
dplyr::bind_rows(lapply(as.character(df$json_col), jsonlite::fromJSON))
# A tibble: 3 x 2
# name points
# <chr> <int>
#1 john NA
#2 doe 10
#3 jane 20
要从函数中提取特定属性,我们可以这样做
bind_rows(lapply(as.character(df$json_col), function(x)
jsonlite::fromJSON(x)[c('name', 'points')]))
在 R4DS 松弛通道上,我收到了一种将 json 数组作为列处理的替代方法。使用它,我发现了另一种方法,似乎在更大的数据集上效果更好。
library(tidyverse)
library(jsonlite)
extract <- function(input, fields){
json_df <- fromJSON(txt=input)
missing <- setdiff(fields, names(json_df))
json_df[missing] <- NA
return (json_df %>% select(fields))
}
df <- data.frame(id=c(1,2,3),
json_col=c('{"name":"john"}','{"name":"doe","points": 10}', '{"name":"jane", "points": 20}'),
stringsAsFactors=FALSE)
df %>%
mutate(json_col = paste0('[',json_col,']'),
json_col = map(json_col, function(x) extract(input=x, fields=c('name', 'points')))) %>%
unnest(cols=c(json_col))
我有一个数据框,其中有一列包含 json 数据。我想从这个 json 数据中提取一些属性到数据框的命名列中。
示例数据
json_col = c('{"name":"john"}','{"name":"doe","points": 10}', '{"name":"jane", "points": 20}')
id = c(1,2,3)
df <- data.frame(id, json_col)
我能够使用
实现这个library(tidyverse)
library(jsonlite)
extract_json_attr <- function(from, attr, default=NA) {
value <- from %>%
as.character() %>%
jsonlite::fromJSON(txt = .) %>%
.[attr]
return(ifelse(is.null(value[[1]]), default, value[[1]]))
}
df <- df %>%
rowwise() %>%
mutate(name = extract_json_attr(json_col, "name"),
points = extract_json_attr(json_col, "points", 0))
在这种情况下,extract_json_attr
需要为要提取的每个属性多次解析 json 列。
有没有更好的方法一次提取所有属性?
我尝试将此函数 return 多个值作为一个列表,但我无法将它与 mutate 一起使用来设置多个列。
extract_multiple <- function(from, attributes){
values <- from %>%
as.character() %>%
jsonlite::fromJSON(txt = .) %>%
.[attributes]
return (values)
}
我可以使用此函数提取所需的值
extract_multiple(df$json_col[1],c('name','points'))
extract_multiple(df$json_col[2],c('name','points'))
但不能将其应用于一次性设置多列。有没有更好的方法来有效地做到这一点?
这是使用 dplyr
bind_rows
的一种方法
dplyr::bind_rows(lapply(as.character(df$json_col), jsonlite::fromJSON))
# A tibble: 3 x 2
# name points
# <chr> <int>
#1 john NA
#2 doe 10
#3 jane 20
要从函数中提取特定属性,我们可以这样做
bind_rows(lapply(as.character(df$json_col), function(x)
jsonlite::fromJSON(x)[c('name', 'points')]))
在 R4DS 松弛通道上,我收到了一种将 json 数组作为列处理的替代方法。使用它,我发现了另一种方法,似乎在更大的数据集上效果更好。
library(tidyverse)
library(jsonlite)
extract <- function(input, fields){
json_df <- fromJSON(txt=input)
missing <- setdiff(fields, names(json_df))
json_df[missing] <- NA
return (json_df %>% select(fields))
}
df <- data.frame(id=c(1,2,3),
json_col=c('{"name":"john"}','{"name":"doe","points": 10}', '{"name":"jane", "points": 20}'),
stringsAsFactors=FALSE)
df %>%
mutate(json_col = paste0('[',json_col,']'),
json_col = map(json_col, function(x) extract(input=x, fields=c('name', 'points')))) %>%
unnest(cols=c(json_col))