Esempio di righe casuali in dataframe


333

Faccio fatica a trovare la funzione appropriata che restituirebbe un numero specificato di righe raccolte casualmente senza sostituzione da un frame di dati in linguaggio R? Qualcuno può darmi una mano?

Risposte:


445

Prima fai alcuni dati:

> 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

Quindi seleziona alcune righe a caso:

> df[sample(nrow(df), 3), ]
           X1         X2
9  -0.3983045  0.7157506
2  -1.1334614 -0.1973846
10 -0.9060305  2.3234110

4
@nikhil Vedi qui e qui per cominciare. Puoi anche digitare ?samplenella console R per leggere su quella funzione.
joran,

10
Qualcuno può spiegare perché il campione (df, 3) non funziona? Perché hai bisogno di df [sample (nrow (df), 3),]?
stackoverflowuser2010,

5
@ stackoverflowuser2010, è possibile digitare? sample e vedere che il primo argomento nella funzione di esempio deve essere un vettore o un numero intero positivo. Non penso che un data.frame funzioni come un vettore in questo caso.
David Braun,

9
Ricorda di impostare il seme (ad es. set.seed(42)) Ogni volta che vuoi riprodurre quel campione specifico.
Cugina Cocaina,

2
sample.intsarebbe leggermente più veloce credo:library(microbenchmark);microbenchmark( sample( 10000, 100 ), sample.int( 10000, 100 ), times = 10000 )
Ari B. Friedman,

199

La risposta di John Colby è la risposta giusta. Tuttavia se sei un dplyrutente c'è anche la risposta sample_n:

sample_n(df, 10)

campiona casualmente 10 righe dal frame di dati. Chiama sample.int, quindi è davvero la stessa risposta con meno battitura (e semplifica l'uso nel contesto di magrittr poiché il frame di dati è il primo argomento).


33

Scrivi uno! Avvolgere la risposta di JC mi dà:

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

Ora rendilo migliore controllando prima se n <= nrow (df) e fermandoti con un errore.


33

Il data.tablepacchetto fornisce la funzione DT[sample(.N, M)], campionando M righe casuali dalla tabella dei dati 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

10

Solo per completezza:

dplyr offre anche di disegnare una proporzione o una frazione del campione di

df %>% sample_frac(0.33)

Questo è molto conveniente, ad esempio nell'apprendimento automatico quando devi fare un certo rapporto di divisione come 80%: 20%


9

EDIT : questa risposta è ora obsoleta, vedere la versione aggiornata .

Nel mio pacchetto R ho migliorato in samplemodo che ora si comporti come previsto anche per i frame di dati:

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

Ciò si ottiene creando sampleun metodo generico S3 e fornendo la funzionalità (banale) necessaria in una funzione. Una chiamata per setMethodrisolvere tutto. È ancora possibile accedere all'implementazione originale base::sample.


1
Cosa c'è di inaspettato nel trattamento dei frame di dati?
un diverso ben

2
@adifferentben: quando chiamo sample.default(df, ...)un frame di dati df, esso preleva dalle colonne del frame di dati, poiché un frame di dati viene implementato come un elenco di vettori della stessa lunghezza.
krlmlr,

Il tuo pacchetto è ancora disponibile? Ho corso install_github('kimisc', 'krlmlr')e ottenuto Error: Does not appear to be an R package (no DESCRIPTION). Qualche modo per aggirare questo?
terdon,

1
@JorisMeys: concordato, ad eccezione della parte "come previsto". Solo perché un frame di dati è implementato come un elenco internamente, ciò non significa che dovrebbe comportarsi come tale. L' [operatore per i frame di dati è un controesempio. Inoltre, per favore dimmi: hai mai usato, solo una volta, il samplecampionamento di colonne da un frame di dati?
krlmlr,

1
@krlmlr L'operatore [non è un controesempio: iris[2]funziona come un elenco, come fa iris[[2]]. Oppure iris$Species, lapply(iris, mean)... I frame di dati sono elenchi. Quindi mi aspetto che si comportino come loro. E sì, ho effettivamente usato sample (myDataframe). Su un set di dati in cui ogni variabile contiene i dati di espressione di un singolo gene. Il tuo metodo specifico aiuta gli utenti alle prime armi, ma cambia anche in modo efficace il sample()comportamento. Nota Uso "come previsto" dal punto di vista di un programmatore. Che è diverso dall'intuizione generale. C'è molto in R che non è compatibile con l'intuizione generale ...;)
Joris Meys,

8

Risposta obsoleta Si prega di utilizzare dplyr::sample_frac()o dplyr::sample_n()invece.

Nel mio pacchetto R c'è una funzione sample.rowssolo per questo scopo:

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

Migliorare samplerendendola una funzione S3 generica è stata una cattiva idea, secondo i commenti di Joris Meys a una risposta precedente .


5

Seleziona un campione casuale da un tipo di tibble in R:

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

nrow prende una tabella e restituisce il numero di righe. Il primo parametro passato a sampleè un intervallo compreso tra 1 e la fine della tabella. Il secondo parametro passato al campione, 150, è quanti campionamenti casuali vuoi. L'affettatura a parentesi quadre specifica le righe degli indici restituiti. La variabile "a" ottiene il valore del campionamento casuale.


4

Potresti farlo:

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

Sopra ho appena creato un frame di dati con 10 colonne e 100 righe, ok?

Ora puoi provarlo con 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

1

Sono nuovo in R, ma stavo usando questo metodo semplice che funziona per me:

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

PS: sentiti libero di notare se ha qualche inconveniente a cui non sto pensando.


0

Potresti farlo:

sample_data = data[sample(nrow(data), sample_size, replace = FALSE), ]
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.