18

我想将 R data.frame 转换为 JSON 对象,以便将其用于使用 d3.js 准备数据可视化。我发现了很多关于如何将 JSON 导入 R 的问题,但很少有关于如何将数据从 R 写入 JSON 的问题。

一个特殊的问题是 JSON 文件需要使用因子嵌套,即 data.frame 的列。我认为从嵌套列表写入可能是一个解决方案,但我已经无法从 data.frame 创建嵌套列表:(

我准备了一个例子:

这代表我的 data.frame(称为“MyData”)。

ID  Location Station   Size Percentage
1     Alpha    Zeta    Big       0.63
2     Alpha    Zeta Medium       0.43
3     Alpha    Zeta  small       0.47
4     Alpha    Yota    Big       0.85
5     Alpha    Yota Medium       0.19
6     Alpha    Yota  small       0.89
7      Beta   Theta    Big       0.09
8      Beta   Theta Medium       0.33
9      Beta   Theta  small       0.79
10     Beta    Meta    Big       0.89
11     Beta    Meta Medium       0.71
12     Beta    Meta  small       0.59

现在,我想把它变成这样的有效 json 格式,包括子节点:

   {
 "name":"MyData",
 "children":[
   {
     "name":"Alpha",
     "children":[
        {
           "name":"Zeta",
           "children":[
              {
                 "name":"Big",
                 "Percentage":0.63
              },
              {
                 "name":"Medium",
                 "Percentage":0.43
              },
              {
                 "name":"Small",
                 "Percentage":0.47
              }
           ]
        },
        {
           "name":"Yota",
           "children":[
              {
                 "name":"Big",
                 "Percentage":0.85
              },
              {
                 "name":"Medium",
                 "Percentage":0.19
              },
              {
                 "name":"Small",
                 "Percentage":0.89
              }
           ]
        }
    ]   
},
    {
     "name":"Zeta",
     "children":[
        {
           "name":"Big",
           "Percentage":0.63
        },
        {
           "name":"Medium",
           "Percentage":0.43
        },
        {
           "name":"Small",
           "Percentage":0.47
        }
     ]
  },
  {
     "name":"Yota",
     "children":[
        {
           "name":"Big",
           "Percentage":0.85
        },
        {
           "name":"Medium",
           "Percentage":0.19
        },
        {
           "name":"Small",
           "Percentage":0.89
        }
     ]
  }
  ]
 }

如果有人可以帮助我,我将非常感激!谢谢你

4

3 回答 3

24

这是一种更简洁的递归方法:

require(RJSONIO)

makeList<-function(x){
  if(ncol(x)>2){
    listSplit<-split(x[-1],x[1],drop=T)
    lapply(names(listSplit),function(y){list(name=y,children=makeList(listSplit[[y]]))})
  }else{
    lapply(seq(nrow(x[1])),function(y){list(name=x[,1][y],Percentage=x[,2][y])})
  }
}


jsonOut<-toJSON(list(name="MyData",children=makeList(MyData[-1])))
cat(jsonOut)
于 2012-10-10T16:15:32.727 回答
2

使用split和的组合subset可能会得到你想要的。例如

library(RJSONIO)
list1<-split(subset(MyData,select=c(-Location)),Mydata$Location)
list2<-lapply(list1,function(x){split(subset(x,select=c(-Station)),x$Station,drop=TRUE)})
list3<-lapply(list2,function(x){lapply(x,function(y){split(subset(y,select=c(-Size,-ID)),y$Size,drop=TRUE)})})
jsonOut<-toJSON(list(MyData=list3))
jsonOut1<-gsub('([^\n]*?): \\{\n "Percentage"','\\{"name":\\1,"Percentage"',jsonOut)
jsonOut2<-gsub('"([^"]*?)": \\{','"name":"\\1","children":\\{',jsonOut1)

cat(jsonOut2)
{
 "name":"MyData","children":{
 "name":"Alpha","children":{
 "name":"Yota","children":{
{"name": "Big","Percentage":   0.85 
},
{"name":"Medium","Percentage":   0.19 
},
{"name":"small","Percentage":   0.89 
} 
},
"name":"Zeta","children":{
{"name": "Big","Percentage":   0.63 
},
{"name":"Medium","Percentage":   0.43 
},
{"name":"small","Percentage":   0.47 
} 
} 
},
"name":"Beta","children":{
 "name":"Meta","children":{
{"name": "Big","Percentage":   0.89 
},
{"name":"Medium","Percentage":   0.71 
},
{"name":"small","Percentage":   0.59 
} 
},
"name":"Theta","children":{
{"name": "Big","Percentage":   0.09 
},
{"name":"Medium","Percentage":   0.33 
},
{"name":"small","Percentage":   0.79 
} 
} 
} 
} 
}
于 2012-10-10T12:37:48.323 回答
0

我正在放弃 user1609452 的回答并回答有关非常规文件层次结构的问题。如果您有一个列,其中某些数据有子级,而有些则没有,请使用以下内容:

makeList<-function(x){ 
if(ncol(x)>2){
    listSplit<-split(x[-1],x[1],drop=T)
    lapply(names(listSplit),function(y){
        if(as.character(listSplit[[y]][1,1]) > 0){
            list(name=y,children=makeList(listSplit[[y]]))
        } else {
            list(name=y,size=listSplit[[y]][1,2])
        }
        })
}else{
    lapply(seq(nrow(x[1])),function(y){list(name=x[,1][y],size=x[,2][y])})
}
}

基本上我们检查当前行是否有更多的孩子,或者它是否只需要附加大小。

于 2016-05-04T17:46:33.277 回答