Các hàng ngẫu nhiên mẫu trong khung dữ liệu


333

Tôi đang vật lộn để tìm chức năng thích hợp sẽ trả về một số lượng hàng được chỉ định ngẫu nhiên được chọn mà không thay thế từ khung dữ liệu bằng ngôn ngữ R? Bất cứ ai có thể giúp tôi ra?

Câu trả lời:


445

Đầu tiên tạo một số dữ liệu:

> 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

Sau đó chọn một số hàng ngẫu nhiên:

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

4
@nikhil Xem tại đâyở đây để bắt đầu. Bạn cũng có thể gõ ?samplevào bảng điều khiển R để đọc về chức năng đó.
Joran

10
Ai đó có thể giải thích tại sao mẫu (df, 3) không hoạt động không? Tại sao bạn cần df [mẫu (nrow (df), 3),]?
stackoverflowuser2010

5
@ stackoverflowuser2010, bạn có thể nhập? sample và thấy rằng đối số đầu tiên trong hàm mẫu phải là một vectơ hoặc một số nguyên dương. Tôi không nghĩ data.frame hoạt động như một vector trong trường hợp này.
David Braun

9
Hãy nhớ đặt hạt giống của bạn (ví dụ set.seed(42)) mỗi lần bạn muốn sao chép mẫu cụ thể đó.
CousinCocaine

2
sample.intTôi sẽ tin nhanh hơn một chút:library(microbenchmark);microbenchmark( sample( 10000, 100 ), sample.int( 10000, 100 ), times = 10000 )
Ari B. Friedman

199

Câu trả lời John Colby đưa ra là câu trả lời đúng. Tuy nhiên nếu bạn là mộtdplyr người dùng thì cũng có câu trả lời sample_n:

sample_n(df, 10)

lấy mẫu ngẫu nhiên 10 hàng từ khung dữ liệu. Nó gọi sample.int, vì vậy thực sự là cùng một câu trả lời với ít gõ hơn (và đơn giản hóa việc sử dụng trong ngữ cảnh của magrittr vì dataframe là đối số đầu tiên).


Lưu ý rằng sample_nchỉ hoạt động trêntbl of data
DJV

33

Viết một cái! Gói câu trả lời của JC cho tôi:

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

Bây giờ làm cho nó tốt hơn bằng cách kiểm tra trước nếu n <= nrow (df) và dừng lại với một lỗi.


33

Các data.tablegói cung cấp các chức năng DT[sample(.N, M)], lấy mẫu M hàng ngẫu nhiên từ bảng dữ liệu 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

Chỉ vì lợi ích hoàn toàn:

dplyr cũng đề nghị vẽ một tỷ lệ hoặc một phần của mẫu bằng cách

df %>% sample_frac(0.33)

Điều này rất thuận tiện, ví dụ như trong học máy khi bạn phải thực hiện một tỷ lệ phân chia nhất định như 80%: 20%


9

EDIT : Câu trả lời này hiện đã lỗi thời, hãy xem phiên bản cập nhật .

Trong gói R của tôi, tôi đã cải tiến sampleđể giờ đây nó hoạt động như mong đợi đối với các khung dữ liệu:

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

Điều này đạt được bằng cách tạo samplemột phương thức chung S3 và cung cấp chức năng cần thiết (tầm thường) trong một chức năng. Một cuộc gọi để setMethodsửa chữa mọi thứ. Việc thực hiện ban đầu vẫn có thể được truy cập thông qua base::sample.


1
Điều gì bất ngờ về việc xử lý các khung dữ liệu của nó?
một ben khác

2
@adifferentben: Khi tôi gọi sample.default(df, ...)cho khung dữ liệu df, nó lấy mẫu từ các cột của khung dữ liệu, vì khung dữ liệu được triển khai dưới dạng danh sách các vectơ có cùng độ dài.
krlmlr

Gói của bạn vẫn còn? Tôi chạy install_github('kimisc', 'krlmlr')và có Error: Does not appear to be an R package (no DESCRIPTION). Có cách nào khác không?
terdon

1
@JorisMeys: Đồng ý, ngoại trừ phần "như mong đợi". Chỉ vì một khung dữ liệu được triển khai như một danh sách trong nội bộ, điều đó không có nghĩa là nó nên hoạt động như một danh sách. Các [nhà điều hành cho khung dữ liệu là một phản ví dụ. Ngoài ra, vui lòng cho tôi biết: Bạn đã bao giờ, chỉ một lần duy nhất, được sử dụng sampleđể lấy mẫu các cột từ khung dữ liệu chưa?
krlmlr

1
@krlmlr [Toán tử không phải là một ví dụ: iris[2]hoạt động giống như một danh sách iris[[2]]. Hoặc iris$Species, lapply(iris, mean)... Khung dữ liệu là danh sách. Vì vậy, tôi mong họ cư xử như họ. Và vâng, tôi đã thực sự sử dụng mẫu (myDataframe). Trên một tập dữ liệu trong đó mỗi biến chứa dữ liệu biểu hiện của một gen. Phương pháp cụ thể của bạn giúp người dùng mới làm quen, nhưng cũng thay đổi hiệu quả cách sample()cư xử. Lưu ý tôi sử dụng "như mong đợi" từ quan điểm của lập trình viên. Mà khác với trực giác chung. Có rất nhiều thứ trong R không tương thích với trực giác chung ...;)
Joris Meys

8

Câu trả lời lỗi thời. Vui lòng sử dụng dplyr::sample_frac()hoặc dplyr::sample_n()thay thế.

Trong gói R của tôi có một chức năng sample.rowschỉ dành cho mục đích này:

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

Tăng cường samplebằng cách biến nó thành một chức năng S3 chung là một ý tưởng tồi, theo nhận xét của Joris Meys cho câu trả lời trước đó .


5

Chọn một mẫu ngẫu nhiên từ một loại có thể hiểu được trong R:

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

nrow mất một tibble và trả về số lượng hàng. Tham số đầu tiên được truyền đến samplelà một phạm vi từ 1 đến hết phần mềm của bạn. Tham số thứ hai được truyền cho mẫu, 150, là bạn muốn có bao nhiêu lần lấy mẫu ngẫu nhiên. Việc cắt khung vuông chỉ định các hàng của các chỉ mục được trả về. Biến 'a' lấy giá trị của mẫu ngẫu nhiên.


3

Bạn có thể làm điều này:

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

Ở trên tôi chỉ tạo một khung dữ liệu với 10 cột và 100 hàng, ok?

Bây giờ bạn có thể lấy mẫu với 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

Tôi mới tham gia R, nhưng tôi đã sử dụng phương pháp dễ dàng này phù hợp với tôi:

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

Tái bút: Hãy lưu ý nếu nó có một số nhược điểm tôi không nghĩ tới.


0

Bạn có thể làm điều này:

sample_data = data[sample(nrow(data), sample_size, replace = FALSE), ]
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.