2012-05-03 14 views
11

Questa è probabilmente una domanda stupida, ma ho letto il Capitolo di Crawley sulla dataframes e perlustrato internet e non sono ancora stati in grado di far funzionare nulla.righe Riassumendo basate su fattore di combinazioni specifiche

Ecco un set di dati campione simile al mio:

> data<-data.frame(site=c("A","A","A","A","B","B"), plant=c("buttercup","buttercup", 
"buttercup","rose","buttercup","rose"), treatment=c(1,1,2,1,1,1), 
plant_numb=c(1,1,2,1,1,2), fruits=c(1,2,1,4,3,2),seeds=c(45,67,32,43,13,25)) 
> data 
    site  plant treatment plant_numb fruits seeds 
1 A buttercup   1   1  1 45 
2 A buttercup   1   1  2 67 
3 A buttercup   2   2  1 32 
4 A  rose   1   1  4 43 
5 B buttercup   1   1  3 13 
6 B  rose   1   2  2 25 

Quello che vorrei fare è creare uno scenario in cui sono sommati "semi" e "frutti" ogni volta unico sito & impianto & trattamento & combinazioni plant_numb esistere. Idealmente, questo si tradurrebbe in una riduzione di righe, ma una conservazione delle colonne originali (cioè ho bisogno l'esempio precedente a guardare come questo :)

site  plant treatment plant_numb fruits seeds 
1 A buttercup   1   1  3 112 
2 A buttercup   2   2  1 32 
3 A  rose   1   1  4 43 
4 B buttercup   1   1  3 13 
5 B  rose   1   2  2 25 

questo esempio è piuttosto semplice (il mio set di dati è ~ 5000 righe), e anche se qui si vedono solo due righe che devono essere sommate, il numero di righe da sommare varia e varia da 1 a ~ 45.

Ho provato rowsum() e tapply() con risultati piuttosto deprimenti fino ad ora (gli errori mi dicono che queste funzioni non sono significative per i fattori), quindi se potessi anche indicarmi la direzione giusta, lo apprezzerei molto!

Grazie mille!

+0

sguardo al tag 'plyr' e' data.table'. Un sacco di domande fondamentalmente affrontano questo. In bocca al lupo! – Chase

+0

Vedi anche http://4dpiecharts.com/2011/12/16/a-quick-primer-on-split-apply-combine-problems/ –

risposta

11

Speriamo che il seguente codice sia abbastanza auto-esplicativo. Usa la funzione di base "aggregato" e in pratica questo è il motivo per cui ogni combinazione unica di sito, pianta, trattamento e pianta non guarda la somma dei frutti e la somma dei semi.

# Load your data 
data <- data.frame(site=c("A","A","A","A","B","B"), plant=c("buttercup","buttercup", 
"buttercup","rose","buttercup","rose"), treatment=c(1,1,2,1,1,1), 
plant_numb=c(1,1,2,1,1,2), fruits=c(1,2,1,4,3,2),seeds=c(45,67,32,43,13,25)) 

# Summarize your data 
aggregate(cbind(fruits, seeds) ~ 
     site + plant + treatment + plant_numb, 
     sum, 
     data = data) 
# site  plant treatment plant_numb fruits seeds 
#1 A buttercup   1   1  3 112 
#2 B buttercup   1   1  3 13 
#3 A  rose   1   1  4 43 
#4 B  rose   1   2  2 25 
#5 A buttercup   2   2  1 32 

L'ordine delle righe cambia (e allineati secondo luogo, piante, ...), ma si spera che non è troppo di una preoccupazione.

Un modo alternativo per farlo sarebbe quello di utilizzare ddply dal pacchetto plyr.

library(plyr) 
ddply(data, .(site, plant, treatment, plant_numb), 
     summarize, 
     fruits = sum(fruits), 
     seeds = sum(seeds)) 
# site  plant treatment plant_numb fruits seeds 
#1 A buttercup   1   1  3 112 
#2 A buttercup   2   2  1 32 
#3 A  rose   1   1  4 43 
#4 B buttercup   1   1  3 13 
#5 B  rose   1   2  2 25 
+0

Impressionante - Stavo solo giocando con aggregato dopo ho fatto la domanda, ma si Mi ha velocizzato molto. Grazie per l'aiuto. Ancora una domanda, però: quando inserisco il codice come hai mostrato, sto ottenendo l'errore "Error in as.data.frame.default (x): non può costringere classe 'formula' in un data.frame" . Qualche idea su come farlo funzionare? – user1371443

+0

Entrambi, sfortunatamente. Sto ottenendo lo stesso messaggio di errore sia per l'esempio e le mie insiemi di dati reali (senza spazi):> aggregati (cbind (frutti, semi) ~ del sito + vegetali + trattamento + plant_numb, somma, data = dati) Errore come .data.frame.default (x): non può forzare la "formula" di classe in un data.frame – user1371443

+0

La soluzione plyr dovrebbe funzionare ancora direi. Ma sembra che tu non abbia una versione formula di aggregato. Quale versione di R stai usando? Penso che l'aggregato abbia permesso l'input di formula dal 2,11 – Dason

4

E per completezza, ecco la soluzione data.table, come suggerito da @Chase. Per set di dati più grandi questo sarà probabilmente il metodo più veloce:

library(data.table) 
data.dt <- data.table(data) 
setkey(data.dt, site) 
data.dt[, lapply(.SD, sum), by = list(site, plant, treatment, plant_numb)] 

    site  plant treatment plant_numb fruits seeds 
[1,] A buttercup   1   1  3 112 
[2,] A buttercup   2   2  1 32 
[3,] A  rose   1   1  4 43 
[4,] B buttercup   1   1  3 13 
[5,] B  rose   1   2  2 25 

La parte lapply(.SD, sum) riassume tutte le colonne che non fanno parte del set di raggruppamento (. Cioè le colonne non nella by funzione)

Problemi correlati