2010-02-14 10 views
6

I dati sperimentali sono espressi come valori di coppie chiave-valore per ciascun esperimento. Una serie di esperimenti correlati è serializzata come un elenco di questi dts in JSON. Questo è analizzabile nella R tramite il pacchetto rjson, ma i dati vengono caricati in una forma che è difficile da analizzareTrasposizione dell'elenco di dizionari JSON per l'analisi in R

data <- fromJSON('[{"k1":"v1","k2":"v2"}, {"k1":"v3","k2":"v4"}]') 

rendimenti

[[1]] 
[[1]]$k1 
[1] "v1" 

[[1]]$k2 
[1] "v2" 


[[2]] 
[[2]]$k1 
[1] "v3" 

[[2]]$k2 
[1] "v4" 

tentativo di trasformare questo in un data.frame direttamente con as.data.frame(data) rese :

k1 k2 k1.1 k2.1 
1 v1 v2 v3 v4 

visualizzazione chiara della sequenza di coppie chiave/valore in tutti gli esperimenti come un elenco monodimensionale.

Quello che voglio è un tavolo più convenzionale con una riga per ogni esperimento, e una colonna per ogni chiave univoca:

k1 k2 
1 v1 v2 
2 v3 v4 

Come posso esprimere in modo pulito questa trasformazione in R?

risposta

11

Le funzioni l*ply possono essere il tuo migliore amico quando si esegue l'elaborazione dell'elenco. Prova questo:

> library(plyr) 
> ldply(data, data.frame) 
    k1 k2 
1 v1 v2 
2 v3 v4 

plyr fa alcune molto bello di elaborazione dietro le quinte a che fare con le cose come le liste irregolari (ad esempio, quando ciascuna lista non contiene lo stesso numero di elementi). Questo è molto comune con JSON e XML ed è difficile da gestire con le funzioni di base.

Oppure, in alternativa utilizzando funzioni base:

> do.call("rbind", lapply(data, data.frame)) 

È possibile utilizzare rbind.fill (da plyr) invece di rbind se avete liste irregolari, ma vorrei consigliare solo usando plyr fin dall'inizio per rendere la vita più facile .

Edit:

quanto riguarda il tuo esempio più complicato, con offerte suggerimento di Hadley con questo facile:

> x<-list(list(k1=2,k2=3),list(k2=100,k1=200),list(k1=5, k3=9)) 
> ldply(x, data.frame) 
    k1 k2 k3 
1 2 3 NA 
2 200 100 NA 
3 5 NA 9 
+0

Come la soluzione plyr, poiché può gestire le variabili che appaiono in un ordine diverso per ciascuna osservazione. Chiamami paranoico, ma ero preoccupato per alcune osservazioni che non avevano alcune variabili. Ecco una variazione che non si interrompe nemmeno in casi molto gravi: x <-list (lista (k1 = 2, k2 = 3), lista (k2 = 100, k1 = 200), lista (k1 = 5)) ; ldply (x, function (z) as.data.frame (t (unlist (z))) –

+2

Penso che una soluzione migliore sia 'ldply (x, data.frame)' – hadley

+0

sceglierei sempre la soluzione plyr:) –

4

Questo è interessante. Il modo più semplice sarebbe quello di sistemare il codice Python in modo che il dict possa essere trasformato più facilmente.

Ma che ne dici di questo?

k1 <- unlist(lapply(data,FUN=function(x){return(x[[1]])})) 
k2 <- unlist(lapply(data,FUN=function(x){return(x[[2]])})) 
data.frame(k1,k2) 

Sarà necessario lanciare K1 e K2 nel tipo di dati corretto ancora, ma questo dovrebbe compiere ciò che si sta cercando.

+2

Una generalizzazione più pulito se avete un sacco di colonne sarebbe: newdata <- lapply (1: length (data [[1]]), function (x) unlist (lapply (data, "[[", x))); newdata <- as.data.frame (newdata); nomi (newdata) <- nomi (dati [[1]]) – brentonk

+0

Posso chiaramente preprocessare il JSON per trasporlo prima di caricarlo, ma il problema è che non lo vedo come "corretto" a tutti: una lista di dicts è il modo più naturale di pensare a questi dati.Un elenco di elenchi è solo il modo più conveniente per il software orientato alla riga di caricarlo in modo denso, non il modo migliore di pensarci. E disimballare manualmente ogni voce non è sostenibile. Il metodo di Bretonk, tuttavia, funziona. (Ho chiaramente bisogno di migliorare il significato di '[[' contrario al solo sottoinsieme ('['), tra le altre cose.) – jrk

+0

La mia soluzione funziona per due colonne, che è chiaramente ciò che la tua domanda implicava. Se hai diverse colonne, ovviamente devi usare una generalizzazione, come il metodo di Brentonk. –