Selecione linhas com maior valor de variável dentro de um grupo em r
-
26-09-2019 - |
Pergunta
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,]
Retorna o índice da lista, não o índice para todos os dados.
Estou tentando devolver o maior valor de b.2
Para cada subgrupo de a.2
. Como posso fazer isso com eficiência?
Solução
a.2<-sample(1:10,100,replace=T)
b.2<-sample(1:100,100,replace=T)
a.3<-data.frame(a.2,b.2)
A resposta de Jonathan Chang recebe o que você pediu explicitamente, mas acho que deseja a linha real do quadro de dados.
sel <- ave(b.2, a.2, FUN = max) == b.2
a.3[sel,]
Outras dicas
o ddply
e ave
As abordagens são bastante intensivas em recursos, eu acho. ave
Falha ficando sem memória para o meu problema atual (67.608 linhas, com quatro colunas definindo as teclas exclusivas). tapply
é uma opção útil, mas o que eu geralmente preciso fazer é selecionar todas as linhas com o valor de algo algo para cada chave exclusiva (geralmente definida por mais de uma coluna). A melhor solução que encontrei é fazer uma espécie e depois usar a negação de duplicated
Para selecionar apenas a primeira linha para cada chave exclusiva. Para o exemplo simples aqui:
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),]
Eu acho que o desempenho ganha ave
ou ddply
, pelo menos, são substanciais. É um pouco mais complicado para chaves de várias colunas, mas order
vai lidar com um monte de coisas para classificar e duplicated
Funciona em quadros de dados, por isso é possível continuar usando essa abordagem.
library(plyr)
ddply(a.3, "a.2", subset, b.2 == max(b.2))
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,]
Isso faz o truque, embora um pouco complicado ... mas me permite pegar as linhas para os maiores valores em grupo. Alguma outra idéia?
> 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
a.2<-sample(1:10,100,replace=T)
b.2<-sample(1:100,100,replace=T)
a.3<-data.frame(a.2,b.2)
Com aggregate
, você pode obter o máximo para cada grupo em uma linha:
aggregate(a.3, by = list(a.3$a.2), FUN = max)
Isso produz a seguinte saída:
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