Comment sélectionner des lignes par groupe avec la valeur minimale et contenant des NA dans R

StackOverflow https://stackoverflow.com//questions/21046425

  •  21-12-2019
  •  | 
  •  

Question

Voici un exemple:

set.seed(123)    
data<-data.frame(X=rep(letters[1:3], each=4),Y=sample(1:12,12),Z=sample(1:100, 12))
data[data==3]<-NA

Ce que je dois réaliser, c'est sélectionner la ligne unique de X avec un minimum Y en ignorant NAs :

a 4 68
b 1 4
c 2 64

Quelle est la meilleure façon de procéder ?

Était-ce utile?

La solution

En utilisant le data.table paquet, c'est trivial :

library(data.table)

d <- data.table(data)
d[, min(Y, na.rm=TRUE), by=X]

Vous pouvez aussi utiliser plyr et son ddply fonction:

library(plyr)

ddply(data, .(X), summarise, min(Y, na.rm=TRUE))

Ou en utilisant la base R :

aggregate(X ~ ., data=data, FUN=min)

Sur la base des modifications, j'utiliserais data.table à coup sûr:

d[, .SD[which.min(Y)], by=X]

Il existe cependant des solutions utilisant base R ou d’autres packages.

Autres conseils

Cela ne sélectionne pas les lignes à l'aide d'un index mais renvoie les valeurs souhaitées...

ddply(data, .(X), summarise, min=min(Y, na.rm=T))

  X min
1 a   5
2 b   1
3 c   4

MODIFIER APRÈS COMMENTAIRE:Pour sélectionner toutes les lignes, vous pouvez :

ddply(data, .(X), function(x) arrange(x, Y)[1, ])

  X Y  Z
1 a 4 68
2 b 1  4
3 c 2 64

Ou

data$index <- 1L:nrow(data)
i <- by(data, data$X, function(x) x$index[which.min(x$Y)] )
data[i, ]

   X Y  Z index
1  a 4 68     1
6  b 1  4     6
10 c 2 64    10

Utiliser un sous-ensemble pour chaque lettre peut être utile.

data<-data.frame(X=rep(letters[1:3], each=4),Y=sample(1:12,12))
dataA <- subset(data, data$X=="a")
min(dataA$Y, na.rm=TRUE)
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top