web-dev-qa-db-fra.com

Échantillonnage aléatoire stratifié à partir de la base de données

J'ai un cadre de données dans le format:

head(subset)
# ants  0 1 1 0 1 
# age   1 2 2 1 3
# lc    1 1 0 1 0

J'ai besoin de créer une nouvelle base de données avec des échantillons aléatoires en fonction de l'âge et du niveau de compétence. Par exemple, je veux 30 échantillons d'âge: 1 et lc: 1, 30 échantillons d'âge: 1 et lc: 0, etc. 

J'ai regardé la méthode d'échantillonnage aléatoire comme; 

newdata <- function(subset, age, 30)

Mais ce n'est pas le code que je veux. 

18
user3525533

Je suggérerais d'utiliser soit stratified de mon paquet "splitstackshape", soit sample_n du paquet "dplyr":

## Sample data
set.seed(1)
n <- 1e4
d <- data.table(age = sample(1:5, n, T), 
                lc = rbinom(n, 1 , .5),
                ants = rbinom(n, 1, .7))
# table(d$age, d$lc)

Pour stratified, vous spécifiez essentiellement le jeu de données, les colonnes de stratification et un entier représentant la taille souhaitée pour chaque groupe OR, une décimale représentant la fraction que vous souhaitez renvoyer (par exemple, .1 représente 10% de chaque groupe) .

library(splitstackshape)
set.seed(1)
out <- stratified(d, c("age", "lc"), 30)
head(out)
#    age lc ants
# 1:   1  0    1
# 2:   1  0    0
# 3:   1  0    1
# 4:   1  0    1
# 5:   1  0    0
# 6:   1  0    1

table(out$age, out$lc)
#    
#      0  1
#   1 30 30
#   2 30 30
#   3 30 30
#   4 30 30
#   5 30 30

Pour sample_n, vous créez d'abord une table groupée (à l'aide de group_by), puis spécifiez le nombre d'observations que vous souhaitez. Si vous souhaitez utiliser l'échantillonnage proportionnel à la place, vous devez utiliser sample_frac.

library(dplyr)
set.seed(1)
out2 <- d %>%
  group_by(age, lc) %>%
  sample_n(30)

# table(out2$age, out2$lc)
35

Voici quelques données:

set.seed(1)
n <- 1e4
d <- data.frame(age = sample(1:5,n,TRUE), 
                lc = rbinom(n,1,.5),
                ants = rbinom(n,1,.7))

Vous souhaitez une stratégie de combinaison application/combinaison, dans laquelle vous split votre nom de données.fr (d dans cet exemple), des lignes/observations de chaque sous-échantillon, puis vous combinez ensuite avec rbind. Voici comment ça fonctionne:

sp <- split(d, list(d$age, d$lc))
samples <- lapply(sp, function(x) x[sample(1:nrow(x), 30, FALSE),])
out <- do.call(rbind, samples)

Le résultat:

> str(out)
'data.frame':   300 obs. of  3 variables:
 $ age : int  1 1 1 1 1 1 1 1 1 1 ...
 $ lc  : int  0 0 0 0 0 0 0 0 0 0 ...
 $ ants: int  1 1 0 1 1 1 1 1 1 1 ...
> head(out)
         age lc ants
1.0.2242   1  0    1
1.0.4417   1  0    1
1.0.389    1  0    0
1.0.4578   1  0    1
1.0.8170   1  0    1
1.0.5606   1  0    1
16
Thomas

Voir la fonction strata du paquet sampling . La fonction sélectionne un échantillonnage aléatoire simple stratifié et donne un échantillon en conséquence. Deux colonnes supplémentaires sont ajoutées: probabilités d'inclusion (Prob) et indicateur de strates (Stratum). Voir l'exemple.

require(data.table)
require(sampling)

set.seed(1)
n <- 1e4
d <- data.table(age = sample(1:5, n, T), 
                lc = rbinom(n, 1 , .5),
                ants = rbinom(n, 1, .7))

# Sort
setkey(d, age, lc)

# Population size by strata
d[, .N, keyby = list(age, lc)]
#     age lc    N
#  1:   1  0 1010
#  2:   1  1 1002
#  3:   2  0  993
#  4:   2  1 1026
#  5:   3  0 1021
#  6:   3  1  982
#  7:   4  0  958
#  8:   4  1  940
#  9:   5  0 1012
# 10:   5  1 1056

# Select sample
set.seed(2)
s <- data.table(strata(d, c("age", "lc"), rep(30, 10), "srswor"))

# Sample size by strata
s[, .N, keyby = list(age, lc)]
#     age lc  N
#  1:   1  0 30
#  2:   1  1 30
#  3:   2  0 30
#  4:   2  1 30
#  5:   3  0 30
#  6:   3  1 30
#  7:   4  0 30
#  8:   4  1 30
#  9:   5  0 30
# 10:   5  1 30
14
djhurio

À moins que j'ai mal compris la question, c'est ridiculement facile à faire avec des fonctions simples.

Étape 1: Créez un indicateur de strate à l’aide de la fonction interaction.

Étape 2: Utilisez tapply sur une séquence d'indicateurs de lignes pour identifier les indices de l'échantillon aléatoire.

Étape 3: Sous-configurez les données avec ces index

En utilisant l'exemple de données de @Thomas:

set.seed(1)
n <- 1e4
d <- data.frame(age = sample(1:5,n,TRUE), 
                lc = rbinom(n,1,.5),
                ants = rbinom(n,1,.7))

## stratum indicator
d$group <- interaction(d[, c('age', 'lc')])

## sample selection
indices <- tapply(1:nrow(d), d$group, sample, 30)

## obtain subsample
subsampd <- d[unlist(indices, use.names = FALSE), ]

Vérifier la stratification appropriée

> table(subsampd$group)

1.0 2.0 3.0 4.0 5.0 1.1 2.1 3.1 4.1 5.1 
 30  30  30  30  30  30  30  30  30  30 
1
AdamO