2012-10-10 50 views
17

我想將R data.frame轉換爲JSON對象,以便使用它將其用於使用d3.js準備數據可視化。我發現了很多問題,詢問如何將JSON轉換爲R,但很少介紹如何將數據從R寫入JSON。如何使用R從兒童寫入json

一個特殊的問題是JSON文件需要使用因素(即data.frame的列)進行嵌套。我認爲,從嵌套列表寫可能是一個解決方案,但我已經無法創建從data.frame :(

我已經preprared一個例子的嵌套列表:

這代表我的data.frame(稱爲「邁德特」)

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 
     } 
    ] 
    } 
    ] 
} 

如果有人可以幫助我我將非常感謝! 謝謝

+1

IMO,這與JSON本身無關,就像R內的這種結構,你很好走。 – aL3xa

+0

你是對的,這是沒有JSON特定。我的問題主要是關於如何獲得這個特定的結構。 – Jens

回答

23

這是一個遞歸方法是清潔劑:

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) 
+0

太棒了!現在看起來很完美。 100%有效的json。爲了使d3js與輸出一起工作,我必須將「百分比」更改爲「大小」。但你的方法絕對精彩!我希望我能調整/擴展它。億萬謝謝! – Jens

+1

這可以通過添加一個簡單的過濾器來適應非常規文件層次結構(即當層次結構數量不恆定時):

x2 <- dplyr::filter(x, x[1] != "") ; listSplit <- split(x2[-1], x2[1], drop = TRUE)
PAC

+0

@PAC確切地說,在x2 < - filter(x,x [1]! =「」); listSplit < - split(x2 [-1],x2 [1],drop = TRUE)'緊跟在if(ncol(x)> 2){'並且保持其他所有內容相同? –

2

結合使用splitsubset可能會得到你想要的。例如

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 
} 
} 
} 
} 
} 
+0

是有趣!但是這裏的變量'「Size」'和'「Percentage」'是分開的。變量的每個狀態(即Big)都應該鏈接到單行中的「百分比」值。此外''孩子''agrument失蹤。我會盡力擺脫分裂列表的想法。 thx – Jens

+0

我在'Size'和一些醜陋的正則表達式上添加了一個分割。它不完全是你想要的,但它可能很接近。 – user1609452

+0

aaah現在我明白這是如何工作的。謝謝。雖然它還沒有完全工作,我會投你:)現在json驗證器抱怨。我認爲[]括號缺失。我會嘗試通過調整你的正則表達式來解決這個問題。 – Jens

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])}) 
} 
} 

基本上我們檢查,如果當前行有更多的孩子,或者如果它只是需要有大小追加到它。