I want to turn an R data.frame into a JSON object in order to use it for preparing data visualizations with d3.js. I found a lot of questions that asked how to get JSON into R, but very few on how to write data from R to JSON.
我想将R data.frame转换为JSON对象,以便使用它来使用d3.js准备数据可视化。我发现了许多问题,询问如何将JSON引入R,但很少有关于如何将数据从R写入JSON的问题。
A particular problem is that the JSON file needs to be nested by using factors, i.e. columns of the data.frame. I think that writing from nested lists could be a solution, but I already failed to create a nested list from a data.frame :(
一个特殊的问题是JSON文件需要使用因子(即data.frame的列)嵌套。我认为从嵌套列表编写可能是一个解决方案,但我已经无法从data.frame创建嵌套列表:(
I have preprared an example:
我有预制红外线的例子:
this represents my data.frame (called "MyData").
这代表我的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
now, I want to turn it into something like this valid json format, including the children nodes:
现在,我想将它变成类似这种有效的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
}
]
}
]
}
If anyone could help me out I would be very much grateful! thank you
如果有人能帮助我,我将非常感激!谢谢
3 个解决方案
#1
23
This is a recursive approach which is cleaner:
这是一种更简洁的递归方法:
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)
#2
2
Using a combination of split
and subset
may get what you want. For example
使用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
}
}
}
}
}
#3
0
I am pigging backing off of user1609452's answer and answering the question about non regular file hierarchies. If you have a column where some data have children and some do not, use the following:
我正在回顾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])})
}
}
Basically we check if the current row has more children or if it simply needs to have size appended to it.
基本上我们检查当前行是否有更多子项,或者它是否只需要附加大小。
#1
23
This is a recursive approach which is cleaner:
这是一种更简洁的递归方法:
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)
#2
2
Using a combination of split
and subset
may get what you want. For example
使用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
}
}
}
}
}
#3
0
I am pigging backing off of user1609452's answer and answering the question about non regular file hierarchies. If you have a column where some data have children and some do not, use the following:
我正在回顾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])})
}
}
Basically we check if the current row has more children or if it simply needs to have size appended to it.
基本上我们检查当前行是否有更多子项,或者它是否只需要附加大小。