我有一个数据框,其中列参数的值是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 。
答案 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)
}