2011-05-20 14 views
7

Me gustaría subconjuntar un marco de datos para n filas, que se agrupan por una variable y se ordenan descendiendo por otra variable. Esto estaría claro con un ejemplo:Subconjunto de un marco de datos con las filas top-n para cada grupo, y ordenado por una variable

d1 <- data.frame(Gender = c("M", "M", "F", "F", "M", "M", "F", 
    "F"), Age = c(15, 38, 17, 35, 26, 24, 20, 26)) 

me gustaría obtener 2 filas, que se ordenan descendiendo la edad, para cada género. La salida deseada es:

Gender Age 
F 35 
F 26 
M 38 
M 26 

busqué orden, clase y otras soluciones aquí, pero no pudo encontrar una solución adecuada a este problema. Aprecio tu ayuda.

+1

¿Solo deseas las dos edades más grandes para cada sexo? – kmm

Respuesta

13

Una solución utilizando ddply() de plyr

require(plyr) 
ddply(d1, "Gender", function(x) head(x[order(x$Age, decreasing = TRUE) , ], 2)) 
+0

¡No vi tu respuesta antes de publicar la mía! Mucho mejor. –

+0

que funcionó maravillosamente! Incluso puedo modificar el valor "n". Gracias. – karlos

+0

+1 todavía funciona si hay vínculos. –

1

Estoy seguro de que hay una respuesta mejor, pero aquí es una manera:

require(plyr) 
ddply(d1, c("Gender", "-Age"))[c(1:2, 5:6),-1] 

Si usted tiene una trama de datos más grande que la proporcionó aquí y no desea inspeccionar visualmente qué filas seleccionar, solo use esto:

new.d1=ddply(d1, c("Gender", "-Age"))[,-1] 
pos=match('M',new.d1$Gender) # pos wil show index of first entry of M 
new.d1[c(1:2,pos:(pos+1)),] 
+1

gracias por su solución, Manoel, pero no lo intenté porque la solución Chase 'funcionó para mí. – karlos

+0

@karlos, por supuesto. Su solución es mejor que la mía. De hecho, ayer me ayudó con una pregunta y usó plyr también. No es sorprendente, él usó 'ddply' mejor que yo. –

5

con el paquete data.table

require(data.table) 
dt1<-data.table(d1)# to speedup you can add setkey(dt1,Gender) 
dt1[,.SD[order(Age,decreasing=TRUE)[1:2]],by=Gender] 
+6

En lugar de 'orden (Edad, decreciente = VERDADERO)' puede escribir 'orden (-Age)'. De esta manera puede ordenar por varias columnas cada una en una dirección diferente; por ejemplo, 'orden (-Age, + Height, -Weight)'. –

0

es aún más fácil de lo que si lo que desea es realizar la ordenación:

d1 <- transform(d1[order(d1$Age, decreasing=TRUE), ], Gender=as.factor(Gender)) 

a continuación, puede llamar a:

require(plyr) 
d1 <- ddply(d1, .(Gender), head, n=2) 

a subconjunto de los dos primeros de cada subgrupo de Género.

0

Tengo una sugerencia si es necesario, por ejemplo, las 2 primeras hembras y los machos 3 primeros:

library(plyr) 
m<-d1[order(d1$Age, decreasing = TRUE) , ] 
h<-mapply(function(x,y) head(x,y), split(m$Age,m$Gender),y=c(2,3)) 
ldply (h, data.frame) 

Usted sólo tiene que cambiar los nombres de la trama de datos final.

Cuestiones relacionadas