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

时间:2015-08-21 07:59:09

标签: json r dplyr sapply

我有一个数据框,其中列参数的值是Json数据:

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

我想提取每一行的参数,并将它们作为列 A B1 B2 B3

我该怎么做?

如果可行且有效,我宁愿使用 dplyr

2 个答案:

答案 0 :(得分:3)

在示例数据中,每行包含一个json对象。此格式称为jsonlines又名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结构。

答案 1 :(得分:0)

我实际上有一个类似的问题,我在一个数据帧中有多个变量,这些变量是JSON对象,其中很多是NA,但是我不想删除存在NA的行。我编写了一个函数,该函数传递了一个数据框,该数据框内的id(通常是一个记录ID)以及用引号引起来的变量名以进行解析。该函数将创建两个子集,一个子集用于包含JSON对象的记录,另一个子集跟踪同一变量的NA值记录,然后将这些数据帧合并,并将其组合与原始数据帧合并,从而替换前一个变量。也许它将对您或其他人有所帮助,因为它在某些情况下对我有用。我也没有真正清除它太多,所以如果变量名有点令人困惑,这是我为工作编写的非常临时的函数,我深表歉意。我还应该指出,我确实使用了另一个发布者的想法,即用从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)
}