2013-12-13 77 views
6

Ecco un data.table:R: Forza data.table per calcolare tutte le interazioni

dat = data.table(var1=rnorm(120), var2=rep(c('a','b','c'),40), var3=rep(c(1,2,3,2,1,2,1,2,2,3,1,2),10)) 

dat2 = dat[,list(resp = mean(var1)),by=list(var2, var3)] 

In dat2, interazioni solo esistenti di dat$var2 et dat$var3 sono presenti. Come posso forzare dat2 per contenere i risultati per tutte le 9 possibili interazioni (invece delle 7 righe di dat2) per var2 e var3? Se non ci sono soluzioni dirette con data.table, qual è il modo più semplice per risolvere questo problema?

table(dat$var2, dat$var3) 

    1 2 3 
    a 20 10 10 
    b 20 20 0 
    c 0 30 10 

Naturalmente, per le interazioni in cui non esistono dati in dat, dat2 dovrebbe contenere NA in resp.

+0

Perché non fare solo 'data.table (...)' invece di 'as.data.table (data.frame (...))'? – Arun

+0

Nessun motivo, è stato stupido! L'ho riparato! Grazie –

risposta

6

è possibile impostare il key e poi fare un crossjoin utilizzando CJ nel i in questo modo ...

setkey(dat , var2 , var3) 

# Thanks to @Shadow for pointing out to use unique() in the cross join 
dat[ CJ(unique(var2) , unique(var3)) , mean(var1) ] 
# var2 var3   V1 
#1: a 1 -0.25771923 
#2: a 2 0.04143057 
#3: a 3 0.28878451 
#4: b 1 0.18865887 
#5: b 2 0.53632552 
#6: b 3   NA 
#7: c 1   NA 
#8: c 2 0.38015021 
#9: c 3 0.49809159 

E mo 'di spiegazione, CJ() crea una data.table nel i di x (in questo caso dat) per partecipare. È formato come prodotto incrociato dei vettori forniti a CJ(), che risulta essere proprio quello che stai cercando!

+1

Sono d'accordo che la versione 'CJ' ha più senso di quella 'expand.grid' che ho suggerito sotto. Ma per la generalizzabilità penso ancora che 'dat [CJ (unique (var2), unique (var3)), mean (var1)]' sarebbe più appropriato di usare esplicitamente 'letters [1: 3]' e '1: 3' . – shadow

+0

@shadow sì certo che hai perfettamente ragione, buona chiamata. –