我有一个数据框,其中有一列包含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列才能提取每个属性。
有一种更好的方法来一次提取所有属性吗?
我尝试过此函数以列表形式返回多个值,但是我无法将其与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'))
但是不能将其应用于一次设置多个列。有没有更好的方法可以有效地做到这一点?
答案 0 :(得分:2)
这是使用bind_rows
中的dplyr
的一种方式
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')]))
答案 1 :(得分:0)
在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))