2010-07-27 24 views
6

ho un data.frame che assomiglia a questoR: aggregato colonne di un data.frame

> head(df) 
      Memory Memory Memory Memory Memory  Naive  Naive 
10472501 6.075714 5.898929 6.644946 6.023901 6.332126 8.087944 7.520194 
10509163 6.168941 6.495393 5.951124 6.052527 6.404401 7.152890 8.335509 
10496091 10.125575 9.966211 10.075613 10.310952 10.090649 11.803949 11.274480 
10427035 6.644921 6.658567 6.569745 6.499243 6.990852 8.010784 7.798154 
10503695 8.379494 8.153917 8.246484 8.390747 8.346748 9.540236 9.091740 
10451763 10.986717 11.233819 10.643245 10.230697 10.541396 12.248487 11.823138 

e vorrei trovare la media dei Memory colonne e la media dei Naive colonne. La funzione aggregate aggrega le righe. Questo data.frame potrebbero avere un gran numero di righe, e quindi recepisce quindi applicando aggregate dal colnames dell'originale data.frame mi sembra male, e generalmente è fastidioso:

> head(t(aggregate(t(df),list(colnames(df)), mean))) 
     [,1]  [,2]  
Group.1 "Memory" "Naive" 
10472501 "6.195123" "8.125439" 
10509163 "6.214477" "7.733625" 
10496091 "10.11380" "11.55348" 
10427035 "6.672665" "8.266854" 
10503695 "8.303478" "9.340436" 

Qual è la cosa assolutamente ovvio che mi manca ?

+1

appassionato dagli occhi tra noterete che 8.12 non è il media di 8.08 e 7.52: ci sono alcuni più colonne in realtà. Non molti di più però! –

risposta

8

Io sono un grande sostenitore di riformattare i dati in modo che sia in un formato "lungo". L'utilità del formato lungo è particolarmente evidente quando si tratta di problemi come questo. Fortunatamente, è abbastanza facile per rimodellare i dati come questo in quasi tutti i formati con il pacchetto reshape.

Se ho capito bene la tua domanda, vuoi la media di Memory e Naive per ogni riga. Per qualsiasi motivo, abbiamo bisogno di fare i nomi di colonna unica per reshape::melt().

colnames(df) <- paste(colnames(df), 1:ncol(df), sep = "_") 

Poi, si dovrà creare una colonna ID. Si potrebbe o fai

df$ID <- 1:nrow(df) 

o, se tali rownames sono significativi

df$ID <- rownames(df) 

Ora, con il pacchetto di reshape

library(reshape) 
df.m <- melt(df, id = "ID") 
df.m <- cbind(df.m, colsplit(df.m$variable, split = "_", names = c("Measure", "N"))) 
df.agg <- cast(df.m, ID ~ Measure, fun = mean) 

df.agg dovrebbe apparire come il vostro snippit output desiderato.

Oppure, se si desidera solo i mezzi complessivi attraverso tutte le righe, il suggerimento di Zack funzionerà. Qualcosa di simile

m <- colMeans(df) 
tapply(m, colnames(df), mean) 

Si potrebbe ottenere lo stesso risultato, ma formattato come dataframe con

cast(df.m, .~variable, fun = mean) 
+0

Dare Jo al tick perché questo sembra essere il modo giusto per fare le cose, quindi grazie mille! Ma sì, come dice John, la cosa ovvia che mi mancava era semplicemente la funzione rowMeans, che è qualcosa che non dimenticherò mai più! –

+0

Erm - domanda veloce. Qualsiasi idea del perché 's <- cast (df.m, variabile ID ~, divertimento = var)' mi restituisce una serie di zeri, quando 'divertimento = mean' sembra funzionare bene e 'divertente = sum' funziona anche? La varianza di queste colonne è def non zero. –

+0

Buona cattura! Non so quale fosse l'accordo, ma poiché i nomi delle colonne non erano unici, non si fondevano correttamente. Ho modificato la mia risposta in modo che funzioni ora! – JoFrhwld

0

Penso di aver caricato i tuoi dati senza header=TRUE e quello che hai è una matrice fattore, e così il vostro generalmente buona idea fallisce.

3

Che dire qualcosa di simile

lapply(unique(colnames(df)), function(x) rowMeans(df[,colnames(df) == x])) 
+0

Grazie Jonathan! Questo è ciò che alcune parti del mio cervello mi stavano dicendo che non potevo ricordarlo. –

3

Per chiarire la risposta di Jonathan Chang ... la cosa ciecamente ovvio che ti manca è che appena si può selezionare le colonne ed emettere il comando rowMeans. Quello darà il vettore dei mezzi per ogni riga. Il suo comando si ottiene significa che la riga per ogni gruppo di nomi di colonna unici ed era esattamente quello che stava per scrivere. Con i tuoi dati di esempio il risultato del suo comando è di due liste.

rowMeans è anche molto veloce.

Per rompere il basso, per ottenere i mezzi di tutte le colonne di memoria è appena

rowMeans(df[,colnames(df) == 'Memory']) #or from you example, rowMeans(df[,1:5]) 

E 'il più semplice risposta corretta completo, lo voto e Marco lo corretto se ti piace.

(a proposito, mi piaceva anche la raccomandazione di Jo di tenere generalmente le cose come dati lunghi.)

0
m = matrix(1:12,3) 
colnames(m) = c(1,1,2,2) 

m 

    1 1 2 2 
[1,] 1 4 7 10 
[2,] 2 5 8 11 
[3,] 3 6 9 12 

mt = t(m) 
sapply(by(mt,rownames(mt),colMeans),identity) 

    1 2 
V1 2.5 8.5 
V2 3.5 9.5 
V3 4.5 10.5 
+0

Potete fornire una spiegazione? –

Problemi correlati