Probieren Sie zufällige Zeilen im Datenrahmen aus

333

Ich habe Probleme, die geeignete Funktion zu finden, die eine bestimmte Anzahl von Zeilen zurückgibt, die zufällig ausgewählt wurden, ohne aus einem Datenrahmen in R-Sprache ersetzt zu werden. Kann mir jemand helfen?

Nikil
quelle

Antworten:

445

Machen Sie zuerst einige Daten:

> 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

Wählen Sie dann einige Zeilen nach dem Zufallsprinzip aus:

> df[sample(nrow(df), 3), ]
           X1         X2
9  -0.3983045  0.7157506
2  -1.1334614 -0.1973846
10 -0.9060305  2.3234110
John Colby
quelle
4
@nikhil Siehe hier und hier für den Anfang. Sie können auch ?sampledie R-Konsole eingeben, um Informationen zu dieser Funktion zu erhalten.
Joran
10
Kann jemand erklären, warum sample (df, 3) nicht funktioniert? Warum brauchen Sie df [sample (nrow (df), 3),]?
stackoverflowuser2010
5
@ stackoverflowuser2010 können Sie? sample eingeben und sehen, dass das erste Argument in der Beispielfunktion ein Vektor oder eine positive Ganzzahl sein muss. Ich glaube nicht, dass ein data.frame in diesem Fall als Vektor funktioniert.
David Braun
9
Denken Sie daran, Ihren Samen (z. B. set.seed(42)) jedes Mal einzustellen, wenn Sie diese bestimmte Probe reproduzieren möchten.
CousinCocaine
2
sample.intwäre etwas schneller, glaube ich:library(microbenchmark);microbenchmark( sample( 10000, 100 ), sample.int( 10000, 100 ), times = 10000 )
Ari B. Friedman
199

Die Antwort, die John Colby gibt, ist die richtige Antwort. Wenn Sie jedoch ein dplyrBenutzer sind, gibt es auch die Antwort sample_n:

sample_n(df, 10)

Stichproben zufällig 10 Zeilen aus dem Datenrahmen. Es ruft auf sample.int, ist also wirklich die gleiche Antwort mit weniger Eingabe (und vereinfacht die Verwendung im Kontext von magrittr, da der Datenrahmen das erste Argument ist).

Kasterma
quelle
Beachten Sie, dass sample_nnur auftbl of data
DJV
33

Schreiben Sie eine! Das Einwickeln von JCs Antwort gibt mir:

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

Machen Sie es jetzt besser, indem Sie zuerst prüfen, ob n <= nrow (df) ist, und mit einem Fehler anhalten.

Spacedman
quelle
33

Das data.tablePaket bietet die Funktion DT[sample(.N, M)], M zufällige Zeilen aus der Datentabelle abzutasten 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
Gented
quelle
10

Nur der Vollständigkeit halber:

dplyr bietet auch an, einen Anteil oder Bruchteil der Probe durch zu ziehen

df %>% sample_frac(0.33)

Dies ist sehr praktisch, z. B. beim maschinellen Lernen, wenn Sie ein bestimmtes Aufteilungsverhältnis wie 80%: 20% durchführen müssen

Agile Bohne
quelle
9

BEARBEITEN : Diese Antwort ist jetzt veraltet, siehe die aktualisierte Version .

In meinem R-Paket habe ich es sampleso erweitert , dass es sich jetzt auch für Datenrahmen wie erwartet verhält:

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

Dies wird erreicht, indem sampleeine generische S3-Methode erstellt und die erforderliche (triviale) Funktionalität in einer Funktion bereitgestellt wird. Ein Aufruf, setMethodalles zu reparieren. Auf die ursprüngliche Implementierung kann weiterhin über zugegriffen werden base::sample.

krlmlr
quelle
1
Was ist unerwartet an der Behandlung von Datenrahmen?
Ein anderer Ben
2
@adifferentben: Wenn ich sample.default(df, ...)einen Datenrahmen anrufe df, werden Stichproben aus den Spalten des Datenrahmens abgetastet , da ein Datenrahmen als Liste von Vektoren gleicher Länge implementiert wird.
krlmlr
Ist Ihr Paket noch verfügbar? Ich rannte install_github('kimisc', 'krlmlr')und bekam Error: Does not appear to be an R package (no DESCRIPTION). Wie kann man das umgehen?
Terdon
1
@JorisMeys: Einverstanden, mit Ausnahme des Teils "wie erwartet". Nur weil ein Datenrahmen intern als Liste implementiert ist , bedeutet dies nicht, dass er sich als einer verhalten sollte . Der [Operator für Datenrahmen ist ein Gegenbeispiel. Bitte sagen Sie mir auch: Haben Sie jemals, nur ein einziges Mal, sampleSpalten aus einem Datenrahmen abgetastet?
krlmlr
1
@krlmlr Der Operator [ist kein Gegenbeispiel: Er iris[2]funktioniert wie eine Liste iris[[2]]. Oder iris$Species, lapply(iris, mean)... Datenrahmen sind Listen. Ich erwarte also, dass sie sich wie sie verhalten. Und ja, ich habe tatsächlich sample (myDataframe) verwendet. In einem Datensatz, in dem jede Variable Expressionsdaten eines einzelnen Gens enthält. Ihre spezifische Methode hilft Anfängern, ändert aber auch effektiv das sample()Verhalten. Hinweis Ich verwende "wie erwartet" aus Sicht eines Programmierers. Welches unterscheidet sich von der allgemeinen Intuition. Es gibt eine Menge in R, die nicht mit der allgemeinen Intuition vereinbar ist ...;)
Joris Meys
8

Veraltete Antwort. Bitte verwenden Sie dplyr::sample_frac()oder dplyr::sample_n()stattdessen.

In meinem R-Paket gibt es eine Funktion sample.rowsnur für diesen Zweck:

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

Verbesserung sampledurch eine generische S3 Funktion war eine schlechte Idee zu machen, nach Kommentaren von Joris Meys auf eine vorherige Antwort .

krlmlr
quelle
5

Wählen Sie eine Zufallsstichprobe aus einem Tibble-Typ in R:

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

nrow nimmt ein tibble und gibt die Anzahl der Zeilen zurück. Der erste Parameter, an den übergeben wird, sampleist ein Bereich von 1 bis zum Ende Ihres Tibbles. Der zweite Parameter, der an die Stichprobe 150 übergeben wird, gibt an, wie viele zufällige Stichproben Sie möchten. Das Schneiden in eckigen Klammern gibt die Zeilen der zurückgegebenen Indizes an. Die Variable 'a' erhält den Wert der Zufallsstichprobe.

Eric Leschinski
quelle
3

Sie könnten dies tun:

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

Oben habe ich gerade einen Datenrahmen mit 10 Spalten und 100 Zeilen erstellt, ok?

Jetzt können Sie es probieren mit 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
quelle
1

Ich bin neu in R, aber ich habe diese einfache Methode verwendet, die für mich funktioniert:

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

PS: Fühlen Sie sich frei zu bemerken, wenn es einen Nachteil hat, über den ich nicht nachdenke.

Leopoldo Sanczyk
quelle
0

Sie könnten dies tun:

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