Amostra de linhas aleatórias no quadro de dados

333

Estou lutando para encontrar a função apropriada que retornaria um número especificado de linhas selecionadas aleatoriamente sem substituição de um quadro de dados na linguagem R? Alguém pode me ajudar?

Nikhil
fonte

Respostas:

445

Primeiro faça alguns dados:

> 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

Em seguida, selecione algumas linhas aleatoriamente:

> df[sample(nrow(df), 3), ]
           X1         X2
9  -0.3983045  0.7157506
2  -1.1334614 -0.1973846
10 -0.9060305  2.3234110
John Colby
fonte
4
@nikhil Veja aqui e aqui para iniciantes. Você também pode digitar ?sampleno console do R para ler sobre essa função.
joran
10
Alguém pode explicar por que a amostra (df, 3) não funciona? Por que você precisa de df [sample (nrow (df), 3),]]?
stackoverflowuser2010
5
@ stackoverflowuser2010, você pode digitar? sample e ver que o primeiro argumento na função de amostra deve ser um vetor ou um número inteiro positivo. Eu não acho que um data.frame funcione como um vetor nesse caso.
David Braun
9
Lembre-se de definir sua semente (por exemplo set.seed(42)) toda vez que quiser reproduzir essa amostra específica.
CousinCocaine
2
sample.intseria ligeiramente mais rápido do que eu acredito:library(microbenchmark);microbenchmark( sample( 10000, 100 ), sample.int( 10000, 100 ), times = 10000 )
Ari B. Friedman
199

A resposta que John Colby dá é a resposta certa. No entanto, se você é um dplyrusuário, também há a resposta sample_n:

sample_n(df, 10)

amostras aleatoriamente 10 linhas do quadro de dados. Chama sample.int, então realmente é a mesma resposta com menos digitação (e simplifica o uso no contexto de magrittr, pois o dataframe é o primeiro argumento).

kasterma
fonte
33

Escreva um! Embrulhar a resposta de JC me dá:

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

Agora melhore, verificando primeiro se n <= nrow (df) e parando com um erro.

Spacedman
fonte
33

O data.tablepacote fornece a função DT[sample(.N, M)], amostrando M linhas aleatórias da tabela de dados 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
fonte
10

Apenas por uma questão de integridade:

O dplyr também oferece desenhar uma proporção ou fração da amostra

df %>% sample_frac(0.33)

Isso é muito conveniente, por exemplo, no aprendizado de máquina, quando você precisa fazer uma certa taxa de divisão, como 80%: 20%

Feijão ágil
fonte
9

EDIT : Esta resposta está desatualizada, veja a versão atualizada .

No meu pacote R, aprimorei samplepara que agora se comporte como esperado também para quadros de dados:

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

Isso é obtido criando sampleum método genérico S3 e fornecendo a funcionalidade (trivial) necessária em uma função. Uma chamada para setMethodconsertar tudo. A implementação original ainda pode ser acessada base::sample.

krlmlr
fonte
1
O que é inesperado sobre o tratamento de quadros de dados?
um ben diferente
2
@adifferentben: Quando eu chamo sample.default(df, ...)um quadro de dados df, ele faz uma amostra das colunas do quadro de dados, pois um quadro de dados é implementado como uma lista de vetores do mesmo comprimento.
precisa saber é
Seu pacote ainda está disponível? Eu corri install_github('kimisc', 'krlmlr')e consegui Error: Does not appear to be an R package (no DESCRIPTION). Alguma maneira de contornar isso?
precisa saber é
1
@JorisMeys: Concordou, exceto pela parte "conforme o esperado". Só porque um quadro de dados é implementado como uma lista internamente, isso não significa que ele deva se comportar como um. O [operador para quadros de dados é um contra-exemplo. Além disso, diga-me: você já, apenas uma vez, usou sampleamostras de colunas de um quadro de dados?
Krlmlr # 6/13
1
@krlmlr O operador [não é um contra-exemplo: iris[2]funciona como uma lista, assim como iris[[2]]. Ou iris$Species, lapply(iris, mean)... Quadros de dados são listas. Então, espero que eles se comportem como eles. E sim, eu realmente usei sample (myDataframe). Em um conjunto de dados em que cada variável contém dados de expressão de um único gene. Seu método específico ajuda usuários iniciantes, mas também altera efetivamente a maneira como sample()se comporta. Observe que eu uso "conforme o esperado" da exibição de um programador. O que é diferente da intuição geral. Há muito em R que não é compatível com a intuição geral ...;)
Joris Meys
8

Resposta desatualizada. Por favor, use dplyr::sample_frac()ou em dplyr::sample_n()vez disso.

No meu pacote R, existe uma função sample.rowsapenas para este propósito:

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

Melhorar sampletornando-a uma função S3 genérica foi uma má ideia, de acordo com comentários de Joris Meys a uma resposta anterior .

krlmlr
fonte
5

Selecione uma amostra aleatória de um tipo de petisco em R:

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

nrow pega um petisco e retorna o número de linhas. O primeiro parâmetro transmitido para sampleé um intervalo de 1 ao final da sua rifa. O segundo parâmetro passado para a amostra, 150, é quantas amostras aleatórias você deseja. A divisão entre colchetes especifica as linhas dos índices retornados. A variável 'a' obtém o valor da amostragem aleatória.

Eric Leschinski
fonte
3

Você pode fazer isso:

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

Acima acabei de criar um dataframe com 10 colunas e 100 linhas, ok?

Agora você pode experimentar com 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
fonte
1

Eu sou novo em R, mas estava usando esse método fácil que funciona para mim:

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

PS: Sinta-se à vontade para observar se há alguma desvantagem em que não estou pensando.

Leopoldo Sanczyk
fonte
0

Você pode fazer isso:

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