superponer - Muestra n filas aleatorias por grupo en un marco de datos
superponer graficas en r (5)
Aquí hay una forma, en base, que permite múltiples grupos y muestreos con reemplazo:
n <- 3
resample <- TRUE
index <- 1:nrow(df)
fun <- function(x) sample(x, n, replace = resample)
a <- aggregate(index, by = list(group = df$color), FUN = fun )
df[c(a$x),]
Para agregar otro grupo, inclúyalo en el argumento ''por'' para agregar.
A partir de estas preguntas: muestra aleatoria de filas del subconjunto de un marco de datos R y muestras aleatorias de ejemplo en el marco de datos Puedo ver fácilmente cómo muestrear aleatoriamente (seleccionar) ''n'' filas de un df, o ''n'' filas que se originan en un nivel específico de un factor dentro de un df.
Aquí hay algunos datos de muestra:
df <- data.frame(matrix(rnorm(80), nrow=40))
df$color <- rep(c("blue", "red", "yellow", "pink"), each=10)
df[sample(nrow(df), 3), ] #samples 3 random rows from df, without replacement.
Para, por ejemplo, solo muestrear 3 filas aleatorias de color ''rosado'' - usando la library(kimisc)
:
library(kimisc)
sample.rows(subset(df, color == "pink"), 3)
o escribiendo función personalizada:
sample.df <- function(df, n) df[sample(nrow(df), n), , drop = FALSE]
sample.df(subset(df, color == "pink"), 3)
Sin embargo, quiero muestrear 3 (o n) filas aleatorias de cada nivel del factor. Es decir, la nueva df tendría 12 filas (3 de azul, 3 de rojo, 3 de amarillo, 3 de rosa). Obviamente, es posible ejecutar esto varias veces, crear nuevos archivos PDF para cada color y luego unirlos, pero estoy buscando una solución más simple.
Aquí hay una solución. Dividimos un data.rame en grupos de colores. De cada uno de estos grupos, muestreamos 3 filas. En resultado, obtenemos una lista de data.frames.
df2 <- lapply(split(df, df$color),
function(subdf) subdf[sample(1:nrow(subdf), 3),]
)
Luego, la lista de data.frames se debe fusionar en 1 data.frame:
do.call(''rbind'', df2)
## X1 X2 color
## blue.3 -1.22677188 1.25648082 blue
## blue.4 -0.54516686 -1.94342967 blue
## blue.1 0.44647071 0.16283326 blue
## pink.40 0.23520296 -0.40411906 pink
## pink.34 0.02033939 -0.32321309 pink
## pink.33 -1.01790533 -1.22618575 pink
## red.16 1.86545895 1.11691250 red
## red.11 1.35748078 -0.36044728 red
## red.13 -0.02425645 0.85335279 red
## yellow.21 1.96728782 -1.81388110 yellow
## yellow.25 -0.48084967 0.07865186 yellow
## yellow.24 -0.07056236 -0.28514125 yellow
Consideraría mi función stratified
, que actualmente está alojada como GitHub Gist.
Consíguelo con:
library(devtools) ## To download "stratified"
source_gist("https://gist.github.com/mrdwab/6424112")
Y úsalo con:
stratified(df, "color", 3)
Hay varias características diferentes que son convenientes para el muestreo estratificado. Por ejemplo, también puede tomar un tipo de muestra "sobre la marcha".
stratified(df, "color", 3, select = list(color = c("blue", "red")))
Para darle una idea de lo que hace la función, aquí están los argumentos para stratified
:
-
df
: La entradadata.frame
-
group
: un vector de caracteres de la columna o columnas que forman los "estratos". -
size
: el tamaño de la muestra deseada.- Si el
size
es un valor menor que 1, se toma una muestra proporcional de cada estrato. - Si el
size
es un solo entero de 1 o más, ese número de muestras se toma de cada estrato. - Si
size
es un vector de enteros, se toma el número especificado de muestras para cada estrato. Se recomienda que utilice un vector con nombre . Por ejemplo, si tienes dos estratos, "A" y "B", y querías 5 muestras de "A" y 10 de "B", ingresaríassize = c(A = 5, B = 10)
.
- Si el
-
select
: esto le permite subcontratar los grupos en el proceso de muestreo. Esta es unalist
. Por ejemplo, si su variable degroup
era "Grupo", y contenía tres estratos, "A", "B" y "C", pero solo quería muestrear de "A" y "C", puede usarselect = list(Group = c("A", "C"))
. -
replace
: Para muestreo con reemplazo.
En versiones de dplyr
0.3 y posteriores, esto funciona bien:
df %>% group_by(color) %>% sample_n(size = 3)
Versiones anteriores de dplyr
(versión <= 0.2)
Me puse a responder esto usando dplyr , asumiendo que esto funcionaría:
df %.% group_by(color) %.% sample_n(size = 3)
Pero resulta que en 0.2 existe el método sample_n.grouped_df
S3 pero no está registrado en el archivo NAMESPACE, por lo que nunca se envía. En cambio, tuve que hacer esto:
df %.% group_by(color) %.% dplyr:::sample_n.grouped_df(size = 3)
Source: local data frame [12 x 3]
Groups: color
X1 X2 color
8 0.66152710 -0.7767473 blue
1 -0.70293752 -0.2372700 blue
2 -0.46691793 -0.4382669 blue
32 -0.47547565 -1.0179842 pink
31 -0.15254540 -0.6149726 pink
39 0.08135292 -0.2141423 pink
15 0.47721644 -1.5033192 red
16 1.26160230 1.1202527 red
12 -2.18431919 0.2370912 red
24 0.10493757 1.4065835 yellow
21 -0.03950873 -1.1582658 yellow
28 -2.15872261 -1.5499822 yellow
Presumiblemente esto se solucionará en una futura actualización.
Puede asignar una ID aleatoria a cada elemento que tenga un nivel de factor particular usando ave
. Luego puede seleccionar todas las ID aleatorias en un cierto rango.
rndid <- with(df, ave(X1, color, FUN=function(x) {sample.int(length(x))}))
df[rndid<=3,]
Esto tiene la ventaja de conservar el orden de las filas y los nombres de las filas originales si eso es algo que le interesa. Además, puede reutilizar el vector rndid
para crear subconjuntos de diferentes longitudes con bastante facilidad.