Cómo seleccionar la fila con el valor máximo en cada grupo

Actualmente tengo un problema de la siguiente manera. En un conjunto de datos donde existen múltiples observaciones para cada tema, y ​​quiero hacer un subconjunto de este conjunto de datos donde solo se seleccionan los datos máximos para un registro. Por ejemplo, para un conjunto de datos como a continuación:

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) 

Los sujetos 1, 2 y 3 tienen el mayor valor de p de 5, 17 y 5, respectivamente. ¿Cómo podría primero, encontrar el mayor valor de pt para cada tema, y ​​luego, poner esta observación en otro dataframe? Esto significa que este subconjunto solo tendrá los mayores valores de pt para cada sujeto.

Aquí hay una solución data.table :

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

Si desea mantener todas las entradas correspondientes a los valores máximos de pt dentro de cada grupo:

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

Si solo desea el primer valor máximo de 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 

En este caso, no hace la diferencia, ya que no hay múltiples valores máximos dentro de ningún grupo en sus datos.

El método más intuitivo es usar la función group_by y top_n en dplyr

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

El resultado que obtienes es

  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 solución más corta usando 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 

No estaba seguro de lo que quería hacer con la columna Evento, pero si desea mantener eso también, ¿qué tal

 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 

Aquí usamos ave para mirar la columna "Valor" para cada "ID". Luego determinamos qué valor es el máximo y luego lo convertimos en un vector lógico que podemos usar para subconjunto del data.frame original.

Una solución 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)) 

Esto produce el siguiente dataframe:

  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),])})) 

Usando Base R

Si quieres el mayor valor de pt para un tema, simplemente puedes usar:

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

Otra opción es 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