Exemple de lignes aléatoires dans la trame de données

333

J'ai du mal à trouver la fonction appropriée qui retournerait un nombre spécifié de lignes ramassées au hasard sans remplacement à partir d'une trame de données en langage R? Quelqu'un peut m'aider?

nikhil
la source

Réponses:

445

Faites d'abord quelques données:

> df = data.frame(matrix(rnorm(20), nrow=10))
> df
           X1         X2
1   0.7091409 -1.4061361
2  -1.1334614 -0.1973846
3   2.3343391 -0.4385071
4  -0.9040278 -0.6593677
5   0.4180331 -1.2592415
6   0.7572246 -0.5463655
7  -0.8996483  0.4231117
8  -1.0356774 -0.1640883
9  -0.3983045  0.7157506
10 -0.9060305  2.3234110

Sélectionnez ensuite quelques lignes au hasard:

> df[sample(nrow(df), 3), ]
           X1         X2
9  -0.3983045  0.7157506
2  -1.1334614 -0.1973846
10 -0.9060305  2.3234110
John Colby
la source
4
@nikhil Voir ici et ici pour commencer. Vous pouvez également taper ?sampledans la console R pour en savoir plus sur cette fonction.
joran
10
Quelqu'un peut-il expliquer pourquoi l'échantillon (df, 3) ne fonctionne pas? Pourquoi avez-vous besoin de df [sample (nrow (df), 3),]?
stackoverflowuser2010
5
@ stackoverflowuser2010, vous pouvez taper? sample et voir que le premier argument de l'exemple de fonction doit être un vecteur ou un entier positif. Je ne pense pas qu'un data.frame fonctionne comme un vecteur dans ce cas.
David Braun
9
N'oubliez pas de définir votre graine (par exemple set.seed(42)) chaque fois que vous souhaitez reproduire cet échantillon spécifique.
CousinCocaine
2
sample.intserait un peu plus rapide je crois:library(microbenchmark);microbenchmark( sample( 10000, 100 ), sample.int( 10000, 100 ), times = 10000 )
Ari B. Friedman
199

La réponse que John Colby donne est la bonne réponse. Cependant, si vous êtes un dplyrutilisateur, il y a aussi la réponse sample_n:

sample_n(df, 10)

échantillonne au hasard 10 lignes de la trame de données. Il appelle sample.int, donc c'est vraiment la même réponse avec moins de frappe (et simplifie l'utilisation dans le contexte de magrittr puisque le dataframe est le premier argument).

kasterma
la source
33

Écrivez-en un! Envelopper la réponse de JC me donne:

randomRows = function(df,n){
   return(df[sample(nrow(df),n),])
}

Améliorez-le maintenant en vérifiant d'abord si n <= nrow (df) et en vous arrêtant avec une erreur.

Spacedman
la source
33

Le data.tablepackage fournit la fonction DT[sample(.N, M)], échantillonnant M lignes aléatoires de la table de données DT.

library(data.table)
set.seed(10)

mtcars <- data.table(mtcars)
mtcars[sample(.N, 6)]

    mpg cyl  disp  hp drat    wt  qsec vs am gear carb
1: 14.7   8 440.0 230 3.23 5.345 17.42  0  0    3    4
2: 19.2   6 167.6 123 3.92 3.440 18.30  1  0    4    4
3: 17.3   8 275.8 180 3.07 3.730 17.60  0  0    3    3
4: 21.5   4 120.1  97 3.70 2.465 20.01  1  0    3    1
5: 22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1
6: 15.5   8 318.0 150 2.76 3.520 16.87  0  0    3    2
adouci
la source
10

Par souci d'exhaustivité:

dplyr propose également de prélever une proportion ou une fraction de

df %>% sample_frac(0.33)

C'est très pratique, par exemple dans l'apprentissage automatique lorsque vous devez faire un certain rapport de partage comme 80%: 20%

Haricot agile
la source
9

EDIT : Cette réponse est désormais obsolète, voir la version mise à jour .

Dans mon package R, j'ai amélioré samplepour qu'il se comporte maintenant comme prévu également pour les trames de données:

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

library(kimisc)
example(sample.data.frame)

smpl..> set.seed(42)

smpl..> sample(data.frame(a=c(1,2,3), b=c(4,5,6),
                           row.names=c('a', 'b', 'c')), 10, replace=TRUE)
    a b
c   3 6
c.1 3 6
a   1 4
c.2 3 6
b   2 5
b.1 2 5
c.3 3 6
a.1 1 4
b.2 2 5
c.4 3 6

Ceci est réalisé en créant sampleune méthode générique S3 et en fournissant la fonctionnalité nécessaire (triviale) dans une fonction. Un appel à setMethodtout réparer. L'implémentation d'origine est toujours accessible via base::sample.

krlmlr
la source
1
Qu'est-ce qui est inattendu dans son traitement des trames de données?
un autre ben
2
@adifferentben: Lorsque j'appelle sample.default(df, ...)une trame de données df, elle échantillonne à partir des colonnes de la trame de données, car une trame de données est implémentée comme une liste de vecteurs de la même longueur.
krlmlr
Votre colis est-il toujours disponible? J'ai couru install_github('kimisc', 'krlmlr')et j'ai réussi Error: Does not appear to be an R package (no DESCRIPTION). Quelque chose autour de ça?
terdon
1
@JorisMeys: D'accord, sauf pour la partie "comme prévu". Ce n'est pas parce qu'un bloc de données est implémenté en tant que liste en interne qu'il doit se comporter comme tel. L' [opérateur pour les trames de données est un contre-exemple. Aussi, dites-moi s'il vous plaît: Avez-vous déjà, une seule fois, utilisé samplepour échantillonner des colonnes d'une trame de données?
krlmlr
1
@krlmlr L'opérateur [n'est pas un contre-exemple: iris[2]fonctionne comme une liste, tout comme iris[[2]]. Ou iris$Species, lapply(iris, mean)... les trames de données sont des listes. Je m'attends donc à ce qu'ils se comportent comme eux. Et oui, j'ai en fait utilisé sample (myDataframe). Sur un ensemble de données où chaque variable contient des données d'expression d'un seul gène. Votre méthode spécifique aide les utilisateurs novices, mais change également efficacement le sample()comportement. Remarque J'utilise "comme prévu" du point de vue d'un programmeur. Ce qui est différent de l'intuition générale. Il y a beaucoup dans R qui n'est pas compatible avec l'intuition générale ...;)
Joris Meys
8

Réponse obsolète. Veuillez utiliser dplyr::sample_frac()ou à la dplyr::sample_n()place.

Dans mon package R, il y a une fonction sample.rowsjuste à cet effet:

install.packages('kimisc')

library(kimisc)
example(sample.rows)

smpl..> set.seed(42)

smpl..> sample.rows(data.frame(a=c(1,2,3), b=c(4,5,6),
                               row.names=c('a', 'b', 'c')), 10, replace=TRUE)
    a b
c   3 6
c.1 3 6
a   1 4
c.2 3 6
b   2 5
b.1 2 5
c.3 3 6
a.1 1 4
b.2 2 5
c.4 3 6

L'amélioration en sampleen faisant une fonction S3 générique était une mauvaise idée, selon les commentaires de Joris Meys à une réponse précédente .

krlmlr
la source
5

Sélectionnez un échantillon aléatoire dans un type de tibble dans R:

library("tibble")    
a <- your_tibble[sample(1:nrow(your_tibble), 150),]

nrow prend un tibble et retourne le nombre de lignes. Le premier paramètre transmis à sampleest une plage de 1 à la fin de votre tibble. Le deuxième paramètre transmis à l'échantillon, 150, est le nombre d'échantillons aléatoires que vous souhaitez. Le découpage entre crochets spécifie les lignes des indices renvoyés. La variable «a» obtient la valeur de l'échantillonnage aléatoire.

Eric Leschinski
la source
4

Vous pouvez faire ceci:

library(dplyr)

cols <- paste0("a", 1:10)
tab <- matrix(1:1000, nrow = 100) %>% as.tibble() %>% set_names(cols)
tab
# A tibble: 100 x 10
      a1    a2    a3    a4    a5    a6    a7    a8    a9   a10
   <int> <int> <int> <int> <int> <int> <int> <int> <int> <int>
 1     1   101   201   301   401   501   601   701   801   901
 2     2   102   202   302   402   502   602   702   802   902
 3     3   103   203   303   403   503   603   703   803   903
 4     4   104   204   304   404   504   604   704   804   904
 5     5   105   205   305   405   505   605   705   805   905
 6     6   106   206   306   406   506   606   706   806   906
 7     7   107   207   307   407   507   607   707   807   907
 8     8   108   208   308   408   508   608   708   808   908
 9     9   109   209   309   409   509   609   709   809   909
10    10   110   210   310   410   510   610   710   810   910
# ... with 90 more rows

Ci-dessus, je viens de créer une trame de données avec 10 colonnes et 100 lignes, d'accord?

Vous pouvez maintenant l'échantillonner avec sample_n:

sample_n(tab, size = 800, replace = T)
# A tibble: 800 x 10
      a1    a2    a3    a4    a5    a6    a7    a8    a9   a10
   <int> <int> <int> <int> <int> <int> <int> <int> <int> <int>
 1    53   153   253   353   453   553   653   753   853   953
 2    14   114   214   314   414   514   614   714   814   914
 3    10   110   210   310   410   510   610   710   810   910
 4    70   170   270   370   470   570   670   770   870   970
 5    36   136   236   336   436   536   636   736   836   936
 6    77   177   277   377   477   577   677   777   877   977
 7    13   113   213   313   413   513   613   713   813   913
 8    58   158   258   358   458   558   658   758   858   958
 9    29   129   229   329   429   529   629   729   829   929
10     3   103   203   303   403   503   603   703   803   903
# ... with 790 more rows
igorkf
la source
1

Je suis nouveau dans R, mais j'utilisais cette méthode simple qui fonctionne pour moi:

sample_of_diamonds <- diamonds[sample(nrow(diamonds),100),]

PS: N'hésitez pas à noter s'il y a un inconvénient auquel je ne pense pas.

Leopoldo Sanczyk
la source
0

Vous pouvez faire ceci:

sample_data = data[sample(nrow(data), sample_size, replace = FALSE), ]
Mohammad
la source