R:JSON到data.frame的通用展平

Sim*_*Sim 11 json r plyr dataframe data.table

这个问题是关于将任何非循环同构或异构数据结构集合转换为数据帧的通用机制.在处理许多JSON文档或使用大型字典数组的JSON文档时,这可能特别有用.

有迹象表明,与操纵深度嵌套的JSON结构和使用功能,比如将他们变成dataframes处理几个做题plyr,lapply等所有的我已经找到了问题和答案有关具体情况,而不是提供一个通用的方法来处理的集合复杂的JSON数据结构.

在Python和Ruby中,我通过实现通用数据结构展平实用程序得到了很好的服务,该实用程序使用数据结构中叶节点的路径作为展平数据结构中该节点的值的名称.例如,该值my_data[['x']][[2]][['y']]将显示为result[['x.2.y']].

如果有一个这些数据结构的集合可能不是完全同质的,那么成功展平到数据帧的关键是发现所有可能的数据帧列的名称,例如,通过采用所有键/名称的联合.单独展平的数据结构中的值.

这似乎是一个常见的模式,所以我想知道是否有人已经为R构建了这个.如果不是,我将构建它,但鉴于R的独特的基于承诺的数据结构,我很欣赏有关实现方法的建议最小化堆抖动.

shh*_*its 9

嗨@Sim我有理由反思你昨天定义的问题:

flatten<-function(x) {
    dumnames<-unlist(getnames(x,T))
    dumnames<-gsub("(*.)\\.1","\\1",dumnames)
    repeat {
        x <- do.call(.Primitive("c"), x)
        if(!any(vapply(x, is.list, logical(1)))){
           names(x)<-dumnames
           return(x)
        }
    }
}
getnames<-function(x,recursive){

    nametree <- function(x, parent_name, depth) {
        if (length(x) == 0) 
            return(character(0))
        x_names <- names(x)
        if (is.null(x_names)){ 
            x_names <- seq_along(x)
            x_names <- paste(parent_name, x_names, sep = "")
        }else{ 
            x_names[x_names==""] <- seq_along(x)[x_names==""]
            x_names <- paste(parent_name, x_names, sep = "")
        }
        if (!is.list(x) || (!recursive && depth >= 1L)) 
            return(x_names)
        x_names <- paste(x_names, ".", sep = "")
        lapply(seq_len(length(x)), function(i) nametree(x[[i]], 
            x_names[i], depth + 1L))
    }
    nametree(x, "", 0L)
}
Run Code Online (Sandbox Code Playgroud)

(getnames改编自AnnotationDbi ::: make.name.tree)

(flatten改编自此处的讨论如何在没有强制的情况下将列表展平到列表?)

举个简单的例子

my_data<-list(x=list(1,list(1,2,y='e'),3))

> my_data[['x']][[2]][['y']]
[1] "e"

> out<-flatten(my_data)
> out
$x.1
[1] 1

$x.2.1
[1] 1

$x.2.2
[1] 2

$x.2.y
[1] "e"

$x.3
[1] 3

> out[['x.2.y']]
[1] "e"
Run Code Online (Sandbox Code Playgroud)

所以结果是一个扁平的列表,大致有你建议的命名结构.也避免了强制,这是一个加号.

一个更复杂的例子

library(RJSONIO)
library(RCurl)
json.data<-getURL("http://www.reddit.com/r/leagueoflegends/.json")
dumdata<-fromJSON(json.data)
out<-flatten(dumdata)
Run Code Online (Sandbox Code Playgroud)

UPDATE

天真的方式去除尾随.1

my_data<-list(x=list(1,list(1,2,y='e'),3))
gsub("(*.)\\.1","\\1",unlist(getnames(my_data,T)))

> gsub("(*.)\\.1","\\1",unlist(getnames(my_data,T)))
[1] "x.1"   "x.2.1" "x.2.2" "x.2.y" "x.3"  
Run Code Online (Sandbox Code Playgroud)