A partir de ces questions - Échantillon aléatoire de lignes d'un sous-ensemble d'une R dataframe & Exemples de lignes aléatoires dans dataframe I permet de voir facilement 'lignes qui proviennent d'un niveau spécifique d'un facteur dans un df.
Voici quelques exemples de données:
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.
Pour par exemple échantillonnez simplement 3 lignes aléatoires de la couleur 'rose' - en utilisant library(kimisc)
:
library(kimisc)
sample.rows(subset(df, color == "pink"), 3)
ou écrire une fonction personnalisée:
sample.df <- function(df, n) df[sample(nrow(df), n), , drop = FALSE]
sample.df(subset(df, color == "pink"), 3)
Cependant, je veux échantillonner 3 (ou n) lignes aléatoires de chaque niveau du facteur. C'est à dire. la nouvelle df aurait 12 rangées (3 de bleu, 3 de rouge, 3 de jaune, 3 de rose). Il est évidemment possible de l'exécuter plusieurs fois, de créer newdfs pour chaque couleur, puis de les lier entre elles, mais je cherche une solution plus simple.
Vous pouvez affecter un ID aléatoire à chaque élément ayant un niveau de facteur particulier en utilisant ave
. Ensuite, vous pouvez sélectionner tous les identifiants aléatoires dans une certaine plage.
rndid <- with(df, ave(X1, color, FUN=function(x) {sample.int(length(x))}))
df[rndid<=3,]
Cela présente l'avantage de préserver l'ordre et le nom des lignes d'origine si cela vous intéresse. De plus, vous pouvez réutiliser le vecteur rndid
pour créer assez facilement un sous-ensemble de longueurs différentes.
Dans les versions de dplyr
0.3 et versions ultérieures, cela fonctionne parfaitement:
df %>% group_by(color) %>% sample_n(size = 3)
dplyr
(version <= 0.2)J'ai décidé de répondre à cela en utilisant dplyr , en supposant que cela fonctionnerait:
df %.% group_by(color) %.% sample_n(size = 3)
Mais il se trouve qu'en 0.2 la méthode sample_n.grouped_df
S3 existe mais qu'elle n'est pas enregistrée dans le fichier NAMESPACE, elle n'est donc jamais distribuée. Au lieu de cela, je devais faire ceci:
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
Vraisemblablement, cela sera corrigé dans une future mise à jour.
Je considérerais ma fonction stratified
, qui est actuellement hébergée en tant que GitHub Gist.
Obtenez le avec:
library(devtools) ## To download "stratified"
source_Gist("https://Gist.github.com/mrdwab/6424112")
Et utilisez-le avec:
stratified(df, "color", 3)
Plusieurs caractéristiques différentes sont pratiques pour l’échantillonnage stratifié. Par exemple, vous pouvez également prendre un échantillon "à la volée".
stratified(df, "color", 3, select = list(color = c("blue", "red")))
Pour vous donner une idée de ce que fait la fonction, voici les arguments de stratified
:
df
: L'entrée data.frame
group
: Un vecteur de caractère de la colonne ou des colonnes qui constituent les "strates".size
: La taille d'échantillon souhaitée .size
est une valeur inférieure à 1, un échantillon proportionnel est tiré de chaque strate.size
est un entier unique de 1 ou plus, ce nombre d'échantillons est pris dans chaque strate.size
est un vecteur d’entiers, le nombre d’échantillons spécifié est prélevé pour chaque strate. Il est recommandé d'utiliser un vecteur named. Par exemple, si vous avez deux strates, "A" et "B", et que vous voulez 5 échantillons de "A" et 10 de "B", vous devez entrer size = c(A = 5, B = 10)
.select
: Cela vous permet de sous-définir les groupes dans le processus d'échantillonnage. Ceci est une list
. Par exemple, si votre variable group
était "Groupe" et qu'elle contenait trois strates, "A", "B" et "C", mais que vous souhaitiez uniquement échantillonner à partir de "A" et "C", vous pouvez utiliser select = list(Group = c("A", "C"))
.replace
: Pour échantillonnage avec remplacement.Voici une solution. Nous divisons un data.frame en groupes de couleurs. Ensuite, nous échantillonnons 3 lignes de chaque groupe. Cela donne une liste de data.frames.
df2 <- lapply(split(df, df$color),
function(subdf) subdf[sample(1:nrow(subdf), 3),]
)
Pour obtenir le résultat souhaité, nous fusionnons la liste de data.frames 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
Voici un moyen, en base, qui permet plusieurs groupes et échantillonnages avec remplacement:
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),]
Pour ajouter un autre groupe, incluez-le dans l'argument 'by' à agréger.