Come selezionare la riga con il valore massimo in ciascun gruppo

Attualmente ho un problema come segue. In un set di dati in cui esistono più osservazioni per ogni sobject e voglio creare un sottoinsieme di questo set di dati in cui sono selezionati solo i dati massimi per un record. Ad esempio, per un set di dati come di seguito:

ID <- c(1,1,1,2,2,2,2,3,3) Value <- c(2,3,5,2,5,8,17,3,5) Event <- c(1,1,2,1,2,1,2,2,2) group <- data.frame(Subject=ID, pt=Value, Event=Event) 

I soggetti 1, 2 e 3 hanno il valore pt maggiore di 5, 17 e 5 rispettivamente. Come potrei in primo luogo, trovare il più grande valore di pt per ogni sobject, e poi mettere questa osservazione in un altro frame di dati? Ciò significa che questo sottoinsieme avrebbe solo i valori pt più alti per ogni sobject.

Ecco una soluzione data.table :

 require(data.table) ## 1.9.2 group <- as.data.table(group) 

Se si desidera mantenere tutte le voci corrispondenti ai valori massimi di pt all'interno di ciascun gruppo:

 group[group[, .I[pt == max(pt)], by=Subject]$V1] # Subject pt Event # 1: 1 5 2 # 2: 2 17 2 # 3: 3 5 2 

Se desideri solo il primo valore massimo di pt :

 group[group[, .I[which.max(pt)], by=Subject]$V1] # Subject pt Event # 1: 1 5 2 # 2: 2 17 2 # 3: 3 5 2 

In questo caso, non fa differenza, poiché non ci sono più valori massimi all'interno di alcun gruppo nei tuoi dati.

Il metodo più intuitivo è utilizzare la funzione group_by e top_n in dplyr

  group %>% group_by(Subject) %>% top_n(1, pt) 

Il risultato che ottieni è

  Source: local data frame [3 x 3] Groups: Subject [3] Subject pt Event (dbl) (dbl) (dbl) 1 1 5 2 2 2 17 2 3 3 5 2 

Una soluzione più corta con data.table :

 setDT(group)[, .SD[which.max(pt)], by=Subject] # Subject pt Event # 1: 1 5 2 # 2: 2 17 2 # 3: 3 5 2 

Non ero sicuro di cosa volessi fare riguardo alla colonna degli eventi, ma se vuoi mantenerlo, per quanto riguarda

 isIDmax <- with(dd, ave(Value, ID, FUN=function(x) seq_along(x)==which.max(x)))==1 group[isIDmax, ] # ID Value Event # 3 1 5 2 # 7 2 17 2 # 9 3 5 2 

Qui usiamo per guardare la colonna "Valore" per ogni "ID". Quindi determiniamo quale valore è il massimo e quindi lo trasformiamo in un vettore logico che possiamo utilizzare per suddividere l'originale data.frame.

Una soluzione dplyr :

 > library(dplyr) > ID <- c(1,1,1,2,2,2,2,3,3) > Value <- c(2,3,5,2,5,8,17,3,5) > Event <- c(1,1,2,1,2,1,2,2,2) > group <- data.frame(Subject=ID, pt=Value, Event=Event) > group <- group_by(group, Subject) > summarize(group, max.pt = max(pt)) 

Questo produce il seguente quadro di dati:

  Subject max.pt 1 1 5 2 2 17 3 3 5 
 do.call(rbind, lapply(split(group,as.factor(group$Subject)), function(x) {return(x[which.max(x$pt),])})) 

Utilizzando Base R

Se vuoi il più grande valore di pt per un sobject, puoi semplicemente usare:

  pt_max = as.data.frame(aggregate(pt~Subject, group, max)) 

Un’altra opzione è slice

 library(dplyr) group %>% group_by(Subject) %>% slice(which.max(pt)) # Subject pt Event #    #1 1 5 2 #2 2 17 2 #3 3 5 2