2010-05-12 8 views
9
a.2<-sample(1:10,100,replace=T) 
b.2<-sample(1:100,100,replace=T) 
a.3<-data.frame(a.2,b.2) 

r<-sapply(split(a.3,a.2),function(x) which.max(x$b.2)) 

a.3[r,] 

restituisce l'indice lista, non l'indice per l'intera data.frameselezionare le righe con il più grande valore della variabile all'interno di un gruppo di r

Nel tentativo di restituire il più grande valore della b.2 per ogni sottogruppo di a.2 . Come posso farlo in modo efficiente?

+0

fusione (a.3, id = c ("a.2")) -> H.2; cast (h.2, a.2 ~, max) Fa il trucco in questo esempio ma il computer esaurisce la memoria quando lo applico al set di dati originale. Quindi non mi ha davvero aiutato molto. – Misha

risposta

6
a.2<-sample(1:10,100,replace=T) 
b.2<-sample(1:100,100,replace=T) 
a.3<-data.frame(a.2,b.2) 

La risposta di Jonathan Chang si ottiene quello che hai chiesto esplicitamente, ma credo che si desidera che la riga reale dal frame di dati.

sel <- ave(b.2, a.2, FUN = max) == b.2 
a.3[sel,] 
+0

Questo è stato molto più semplice devo ammetterlo .. Tuttavia la logica dietro il == b.2 è oltre me ... – Misha

+0

L'azione genera un vettore che contiene solo il massimo di b.2 per ogni a.2. Pertanto, dove è == b.2 che imposta un valore di verità purché il frame di dati abbia righe. Stai utilizzando il vettore logico per selezionare le righe nel frame dei dati. Se vuoi vedere come funziona aggiungi il risultato del comando ave al tuo frame di dati e guardalo, confrontandolo con la colonna b.2 - a.3 $ b.max <- ave (b.2, a. 2, FUN = max) . Inoltre, puoi impostare la variabile sel e guardarla nel contesto con - a.3 $ sel <- a.3 $ b.2 == a.3 $ b.max – John

+0

Thx ... Apprezzo i tuoi sforzi. – Misha

1
a.2<-sample(1:10,100,replace=T) 
b.2<-sample(1:100,100,replace=T) 
a.3<-data.frame(a.2,b.2) 
m<-split(a.3,a.2) 
u<-function(x){ 
    a<-rownames(x) 
    b<-which.max(x[,2]) 
    as.numeric(a[b]) 
    } 
r<-sapply(m,FUN=function(x) u(x)) 

a.3[r,] 

Questo è il trucco, anche se un po 'ingombrante ... Ma mi permette di afferrare le righe per i valori più grandi del gruppo. Altre idee?

1
> a.2<-sample(1:10,100,replace=T) 
> b.2<-sample(1:100,100,replace=T) 
> tapply(b.2, a.2, max) 
1 2 3 4 5 6 7 8 9 10 
99 92 96 97 98 99 94 98 98 96 
8
library(plyr) 
ddply(a.3, "a.2", subset, b.2 == max(b.2)) 
+0

Ho provato a utilizzare la funzione ddply ma è dolorosamente lento. Non l'ho fatto a tempo ma è durato una coffecup e un viaggio in bagno mentre la versione ave usava solo .2s nel mio dataset originale (210col * 16000rows). – Misha

+1

Questo sarà risolto nella prossima versione.Ma non puoi aspettarti di ottenere risposte che funzionino con i tuoi dati a meno che non fornisci un esempio realistico! – hadley

10

I ddply e ave approcci sono entrambi abbastanza alta intensità di risorse, credo. ave non riesce a esaurire la memoria per il mio problema corrente (67.608 righe, con quattro colonne che definiscono le chiavi univoche). tapply è una scelta utile, ma quello che in genere devo fare è selezionare tutte le righe complete con il valore-qualcosa-est per ogni chiave univoca (di solito definita da più di una colonna). La soluzione migliore che ho trovato è di fare un ordinamento e quindi utilizzare la negazione di duplicated per selezionare solo la prima riga per ogni chiave univoca. Per il semplice esempio qui:

a <- sample(1:10,100,replace=T) 
b <- sample(1:100,100,replace=T) 
f <- data.frame(a, b) 

sorted <- f[order(f$a, -f$b),] 
highs <- sorted[!duplicated(sorted$a),] 

Credo che l'incremento delle prestazioni oltre ave o ddply, almeno, sono sostanziali. È leggermente più complicato per le chiavi multi-colonna, ma lo standard order gestirà un sacco di cose da ordinare e duplicated funziona su frame di dati, quindi è possibile continuare a utilizzare questo approccio.

+0

Questo è stato il più semplice da usare e funziona perfettamente su più colonne: tutto ciò che devi fare è usare 'cbind' all'interno di' duplicato'. –

0
a.2<-sample(1:10,100,replace=T) 
b.2<-sample(1:100,100,replace=T) 
a.3<-data.frame(a.2,b.2) 

Con aggregate, è possibile ottenere il massimo per ciascun gruppo in una linea:

aggregate(a.3, by = list(a.3$a.2), FUN = max) 

Questo produce il seguente output:

Group.1 a.2 b.2 
1  1 1 96 
2  2 2 82 
... 
8  8 8 85 
9  9 9 93 
10  10 10 97 
Problemi correlati