Como selecionar a linha com o valor máximo em cada grupo

Atualmente tenho um problema como segue. Em um dataset em que existem várias observações para cada assunto, e quero criar um subconjunto desse dataset em que apenas os dados máximos para um registro são selecionados. Por exemplo, para um dataset conforme abaixo:

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) 

Assunto 1, 2 e 3 têm o maior valor de pt de 5, 17 e 5, respectivamente. Como eu poderia primeiro encontrar o maior valor de pt para cada assunto e, em seguida, colocar essa observação em outro quadro de dados? Isso significa que esse subconjunto teria apenas os maiores valores de pt para cada assunto.

Aqui está uma solução de dados:

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

Se você quiser manter todas as inputs correspondentes aos 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 

Se você quiser apenas o primeiro 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 

Nesse caso, não faz diferença, pois não há vários valores máximos em nenhum grupo nos seus dados.

O método mais intuitivo é usar a function group_by e top_n no dplyr

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

O resultado que você recebe é

  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 

Uma solução mais curta 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 

Eu não tinha certeza do que você queria fazer sobre a coluna Evento, mas se você quiser manter isso também, que 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 

Aqui nós usamos ave para olhar a coluna "Valor" para cada "ID". Em seguida, determinamos qual valor é o máximo e, em seguida, o transformamos em um vetor lógico que podemos usar para subconjugar o data.frame original.

Uma solução 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)) 

Isso produz o seguinte quadro de dados:

  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

Se você quer o maior valor de pt para um assunto, você pode simplesmente usar:

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

Outra opção é 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