从 R 数据帧的行中提取 JSON 数据

Extract JSON data from the rows of an R data frame

我有一个数据框,其中 Parameters 列的值为 Json data:

#  Parameters
#1 {"a":0,"b":[10.2,11.5,22.1]}
#2 {"a":3,"b":[4.0,6.2,-3.3]}
...

我想提取每一行的参数并将它们作为列附加到数据框中 A, B1, B2B3.

我该怎么做?

如果可能且高效,我宁愿使用 dplyr

在您的示例数据中,每一行都包含一个 json 对象。这种格式叫做jsonlines aka ndjson,jsonlite包有一个特殊的函数stream_in可以把这样的数据解析成一个数据框:

# Example data
mydata <- data.frame(parameters = c(
  '{"a":0,"b":[10.2,11.5,22.1]}',
  '{"a":3,"b":[4.0,6.2,-3.3]}'
), stringsAsFactors = FALSE)

# Parse json lines
res <- jsonlite::stream_in(textConnection(mydata$parameters))

# Extract columns
a <- res$a
b1 <- sapply(res$b, "[", 1)
b2 <- sapply(res$b, "[", 2)
b3 <- sapply(res$b, "[", 3)

在您的示例中,json 结构相当简单,因此其他建议也适用,但此解决方案将推广到更复杂的 json 结构。

我实际上有一个类似的问题,我在一个数据框中有多个变量,它们是 JSON 个对象,其中很多是 NA,但我不想删除 NA 存在的行。我写了一个函数,它传递了一个数据框,数据框内的id(通常是一个记录ID),以及引号中的变量名来解析。该函数将创建两个子集,一个用于包含 JSON 对象的记录,另一个用于跟踪同一变量的 NA 值记录,然后它连接这些数据框并将它们的组合连接到原始数据框,从而替换前者多变的。也许它会对您或其他人有所帮助,因为它现在在某些情况下对我有用。我也没有真正清理太多,所以如果我的变量名称有点混乱,我深表歉意,因为这是我为工作编写的非常 ad-hoc 的函数。我还应该声明,我确实使用了另一张海报的想法,用从 JSON 对象创建的新变量替换以前的变量。你可以在这里找到:Add (insert) a column between two columns in a data.frame

最后一点:有一个名为 tidyjson 的包,它有一个更简单的解决方案,但显然不能使用列表类型 JSON 对象。至少那是我的解释。

library(jsonlite)
library(stringr)
library(dplyr)

parse_var <- function(df,id, var) {
  m <- df[,var]
  p <- m[-which(is.na(m))]
  n <- df[,id]
  key <- n[-which(is.na(df[,var]))]

  #create df for rows which are NA
  key_na <- n[which(is.na(df[,var]))]
  q <- m[which(is.na(m))]
  parse_df_na <- data.frame(key_na,q,stringsAsFactors = FALSE)  

  #Parse JSON values and bind them together into a dataframe.
  p <- lapply(p,function(x){ 
    fromJSON(x) %>% data.frame(stringsAsFactors = FALSE)}) %>% bind_rows()
  #bind the record id's of the JSON values to the above JSON parsed dataframe and name the columns appropriately.
  parse_df <- data.frame(key,p,stringsAsFactors = FALSE)

## The new variables begin with a capital 'x' so I replace those with my former variables  name
  n <- names(parse_df) %>% str_replace('X',paste(var,".",sep = ""))
  n <- n[2:length(n)]
  colnames(parse_df) <- c(id,n)

  #join the dataframe for NA JSON values and the dataframe containing parsed JSON values, then remove the NA column,q.
  parse_df <- merge(parse_df,parse_df_na,by.x = id,by.y = 'key_na',all = TRUE)

#Remove the new column formed by the NA values#
  parse_df <- parse_df[,-which(names(parse_df) =='q')]

  ####Replace variable that is being parsed in dataframe with the new parsed and names values.######

  new_df <- data.frame(append(df,parse_df[,-which(names(parse_df) == id)],after = which(names(df) == var)),stringsAsFactors = FALSE)
  new_df <- new_df[,-which(names(new_df) == var)]
  return(new_df)
}