2012-10-10 13 views
17

Chcę przekształcić R data.frame w obiekt JSON, aby użyć go do przygotowania wizualizacji danych za pomocą d3.js. Znalazłem wiele pytań, które pytały, jak uzyskać JSON w R, ale bardzo niewiele na temat pisania danych z R do JSON.Jak napisać do JSONA z dziećmi z R

Szczególnym problemem jest to, że plik JSON musi być zagnieżdżony za pomocą współczynników, tj. Kolumn elementu data.frame. Myślę, że pisanie z zagnieżdżonych list może być rozwiązaniem, ale ja już nie udało się utworzyć zagnieżdżone listy z data.frame :(

Mam preprared przykład:

ten reprezentuje moje data.frame (zwany . „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 

teraz chcę, aby przekształcić go w coś takiego ważnego formacie jSON, w tym dzieci węzłów:

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

Jeśli ktoś może mi pomóc Byłbym bardzo wdzięczny! dziękuję

+1

IMO, to nie ma nic wspólnego z JSON per se, po prostu przypominają tę strukturę w R, i jesteś dobry, aby przejść. – aL3xa

+0

masz rację, to jest nic JSON specifc. moje pytanie dotyczyło głównie tego, jak uzyskać tę konkretną strukturę. – Jens

Odpowiedz

23

Jest to rekurencyjny podejście, które jest czystsze:

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

niesamowite! Teraz wygląda idealnie. 100% prawidłowego json. Aby d3js działał z wyjściem musiałem zmienić "Procent" na "rozmiar". Ale twoje podejście jest absolutnie genialne! Mam nadzieję, że mogę go dostosować/rozszerzyć. Miliardy dzięki! – Jens

+1

Można to dostosować do nieregularnych hierarchii plików (tj. Gdy liczba hierarchii nie jest stała) przez dodanie prostego filtru:

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

+0

@PAC dokładnie tam, gdzie następuje jedna kropla w 'x2 <- filter (x, x [1]! = ""); listSplit <- split (x2 [-1], x2 [1], drop = TRUE) 'zaraz po' if (ncol (x)> 2) {'i pozostaw wszystko inne tak samo? –

2

Korzystanie z kombinacji split i subset może uzyskać to, co chcesz. Na przykład

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

tak interesujące! ale tutaj zmienne '" Rozmiar "' i '" Odsetek "' są rozdzielone. Każdy stan zmiennej, tj. Big, powinien być powiązany z wartością procentową w jednym wierszu. Brakuje także agryki "" dzieci ". Postaram się poradzić sobie z twoim pomysłem dzielenia list. thx – Jens

+0

Dodałem podział na "Rozmiar" i niektóre brzydkie wyrażenie regularne. Nie jest to dokładnie to, czego chcesz, ale może być blisko. – user1609452

+0

aaah teraz rozumiem, jak to działa. Dziękuję Ci. Chociaż nadal nie działa w pełni, zagłosuję za tobą :) Weryfikator json teraz narzeka. Myślę, że brakuje nawiasów []. Spróbuję to naprawić, dostosowując Twoje przykłady do wyrażenia regularnego. – Jens

0

mam korek odejściu odpowiedzi user1609452 i odpowiadając na pytanie o regularnych spoza hierarchii plików. Jeśli masz kolumnę gdzie niektóre dane mają dzieci, a niektóre nie, użyj następujących:

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

Zasadniczo możemy sprawdzić, czy obecny rząd ma więcej dzieci, czy też po prostu musi mieć rozmiar dołączana do niego.