2013-09-24 14 views
9

Voglio gli stessi risultati di R summarizing multiple columns with data.table ma per diverse funzioni di riepilogo.R statistiche multiple per più colonne con data.table

Ecco un esempio

data <- as.data.table(list(x1 = runif(200), x2 = 10*runif(200), group = factor(sample(letters[1:2])))) 

res <- data[, rbindlist(lapply(.SD, function(x) { 
       return(list(name = "varname", mean = mean(x), sd = sd(x))) 
      })) 
      , by = group, .SDcols = c("x1", "x2") 
      ] 

E ottenere il seguente risultato:

group name  mean  sd 
1:  b varname 0.5755798 0.2723767 
2:  b varname 5.5108886 2.7649262 
3:  a varname 0.4906111 0.3060961 
4:  a varname 4.7780189 2.9740149 

Come posso ottenere i nomi delle colonne ('x1', 'x2') nella seconda colonna? Suppongo di dover sostituire lo rbindlist con qualcos'altro, ma cosa? C'è una soluzione semplice?

risposta

13

Un modo alternativo sarebbe quello di costruire la propria funzione in modo che si può evitare questo rbindlist involucro (che trovo non è necessario), che la dà libertà di costruire la tua funzione nel modo desiderato:

tmp <- function(x) { 
    mm <- colMeans(x) 
    ss=sapply(x, sd) 
    list(names=names(x), mean=mm, sd=ss) 
} 

data[, tmp(.SD), by=group] 
    group names  mean  sd 
1:  a x1 0.4988514 0.2770122 
2:  b x1 0.5246786 0.3014248 
3:  a x2 4.8031253 2.7978401 
4:  b x2 4.9104108 2.9135656 
+0

+1 Questo è molto più elegante. – juba

4

È possibile iterare il lapply su names(.SD) anziché .SD. Qualcosa di simile a questo:

data <- as.data.table(list(x1 = runif(200), x2 = 10*runif(200), group = factor(sample(letters[1:2])))) 
res <- data[, rbindlist(lapply(names(.SD), function(name) { 
       return(list(name = name, mean = mean(.SD[[name]]), sd = sd(.SD[[name]]))) 
      })) 
      , by = group, .SDcols = c("x1", "x2")] 

che dà:

group name  mean  sd 
1:  b x1 0.5344272 0.2697610 
2:  b x2 4.7628178 2.8313825 
3:  a x1 0.5008916 0.2686017 
4:  a x2 4.6175027 2.8942875 
Problemi correlati