2012-03-09 22 views
12

¿Hay una buena manera de obtener una muestra de filas de parte de un marco de datos?Muestra aleatoria de filas del subconjunto de un dataframe R

Si sólo tengo datos como

gender <- c("F", "M", "M", "F", "F", "M", "F", "F") 
age <- c(23, 25, 27, 29, 31, 33, 35, 37) 

entonces puedo probar fácilmente las edades de tres de los Fs con

sample(age[gender == "F"], 3) 

y obtener algo así como

[1] 31 35 29 

pero si convierto estos datos en un marco de datos

mydf <- data.frame(gender, age) 

no puedo usar lo obvio

sample(mydf[mydf$gender == "F", ], 3) 

aunque puedo inventar algo enrevesado con un número absurdo de soportes como

mydf[sample((1:nrow(mydf))[mydf$gender == "F"], 3), ] 

y conseguir lo que quiero, que es algo así como

gender age 
7  F 35 
4  F 29 
1  F 23 

¿Hay alguna manera mejor que me tome menos tiempo para resolver cómo escribir?

Respuesta

17

Su forma enrevesada es más o menos cómo hacerlo - Creo que todas las respuestas serán variaciones sobre ese tema.

Por ejemplo, me gusta generar los mydf$gender=="F" índices primera:

idx <- which(mydf$gender=="F") 

Entonces me muestra a partir de que:

mydf[ sample(idx,3), ] 

Así, en una línea (si bien, se reduce el número absurdo de soportes y posiblemente haga que su código sea más fácil de entender al tener varias líneas):

mydf[ sample(which(mydf$gender=='F'), 3), ] 

¡Mientras que "cuando soy un hacker!" una parte de mí prefiere el one-liner, la parte sensata de mí dice que aunque el dos líneas es de dos líneas, es mucho más comprensible, es solo tu elección.

+0

6 soportes (ya sea en una o dos líneas) es sin duda mejor que 10. – Henry

+0

Todavía no puedo creer que no haya una manera fácil de llevar a cabo un procedimiento estadístico funcional en R. Tiene que haber una aplicación, es decir, un paquete para eso. –

9

Usted dice no puedo usar lo obvio:

sample(mydf[mydf$gender == "F", ], 3) 

pero se puede escribir su propia función para hacerlo:

sample.df <- function(df, n) df[sample(nrow(df), n), , drop = FALSE] 

luego ejecutarlo en su selección de subconjuntos:

sample.df(mydf[mydf$gender == "F", ], 3) 
# gender age 
# 5  F 31 
# 4  F 29 
# 1  F 23 

(Personalmente me parece sample.df(subset(mydf, gender == "F"), 3) más fácil leer.)

2

Esto es ahora más sencillo con la versión mejorada de sample en mi paquete:

library(devtools); install_github('kimisc', 'krlmlr') 

library(kimisc) 
sample.rows(subset(mydf, gender == "F"), 3) 

Ver también este related answer para obtener más detalles.

Cuestiones relacionadas