2017-05-19 15 views
8

Tôi có một vài tập dữ liệu lớn mà tôi đang cố kết hợp. Tôi đã tạo ra một ví dụ đồ chơi về những gì tôi muốn làm. Tôi có ba bảng:Tham gia dữ liệu.tôi bằng cách lấy mẫu

require(data.table) 
set.seed(151) 
x <- data.table(a=1:100000) 
y <- data.table(b=letters[1:20],c=sample(LETTERS[1:4])) 
proportion <- data.table(expand.grid(a=1:100000,c=LETTERS[1:4])) 
proportion[,prop:=rgamma(4,shape = 1),by=a] 
proportion[,prop:=prop/sum(prop),by=a] 

Ba bảng là x, y, và proportion. Đối với mỗi phần tử trong x Tôi muốn lấy mẫu từ toàn bộ bảng y sử dụng xác suất từ ​​bảng proportion và kết hợp chúng thành một bảng khác. Phương pháp mà tôi đưa ra là:

temp <- setkey(setkey(x[,c(k=1,.SD)],k)[y[,c(k=1,.SD)],allow.cartesian=TRUE][,k:=NULL],a,c) 
temp <- temp[setkey(proportion,a,c)][,prop:=prop/.N,by=.(a,c)] # Uniform distribution within the same 'c' column group 
chosen_pairs <- temp[,.SD[sample(.N,5,replace=FALSE,prob = prop)],by=a] 

Nhưng phương pháp này là bộ nhớ chuyên sâu và chậm khi nó nối chéo hai bảng trước và sau đó lấy mẫu từ nó. Có cách nào để thực hiện nhiệm vụ này theo cách hiệu quả (bộ nhớ và thời gian) không?

+0

Tại sao bạn tính toán lại xác suất trong dòng thứ hai của giải pháp? – minem

+0

@ MārtiņšMiglinieks Tôi chuẩn hóa các xác suất như đối với một cặp '(a, c)' đã cho có thể có nhiều 'b' –

+0

Lookup' .EACHI', khi tham gia chéo cho phép bạn xử lý phần được nối trong mỗi hoạt động, mà không giải quyết việc tham gia đầy đủ trong mem. – Shape

Trả lời

1

Tôi gặp phải sự cố hơi giống với câu hỏi this. tôi quấn giải pháp của bạn vào chức năng để so sánh tốt hơn:

goreF <- function(x,y,proportion){ 
    temp <- setkey(setkey(x[, c(k = 1, .SD)], k)[y[,c(k = 1, .SD)], 
            allow.cartesian = TRUE][, k := NULL], 
      a, c) 
    temp <- temp[setkey(proportion, a, c)][, prop := prop/.N, by = .(a, c)] 
    chosen_pairs <- temp[, .SD[sample(.N, 5, replace = FALSE, prob = prop)], 
        by = a] 
    chosen_pairs 
} 

cách tiếp cận của tôi:

myFunction <- function(x, y, proportion){ 
    temp <- setkey(setkey(x[, c(k = 1, .SD)], k)[y[,c(k = 1, .SD)], 
              allow.cartesian = TRUE][, k := NULL], 
      a, c) 
    temp <- temp[setkey(proportion, a, c)][, prop := prop/.N, by = .(a, c)] 
    chosen_pairs <- temp[, sample(.I, 5, replace = FALSE, prob = prop), by = a] 
    indexes <- chosen_pairs[[2]] 
    temp[indexes] 
} 

require(rbenchmark) 
benchmark(myFunction(x, y, proportion), goreF(x, y, proportion), 
     replications = 1, 
     columns = c("test", "replications", "elapsed", "relative", 
        "user.self", "sys.self")) 
          test replications elapsed relative user.self sys.self 
2  goreF(x, y, proportion)   1 19.83 21.323  19.35  0.13 
1 myFunction(x, y, proportion)   1 0.93 1.000  0.86  0.08 

lẽ có thể được tìm thấy nhiều cải tiến hơn, tôi sẽ cập nhật, nếu tìm thấy bất kỳ. Hai hoạt động đầu tiên có vẻ quá phức tạp, có thể chúng có thể được rút ngắn, nhưng, vì tôi không thấy rằng chúng tác động đến thời gian tính toán, nên tôi đã không viết lại chúng.

Cập nhật:

Như đã chỉ ra trong câu hỏi tôi đã đề cập ở phần đầu, bạn có thể gặp rắc rối với myFunction, nếu nhóm của bạn sẽ chỉ chứa một phần tử. Vì vậy, tôi đã sửa đổi nó, dựa trên các nhận xét từ bài đăng đó.

myFunction2 <- function(x, y, proportion){ 
    temp <- setkey(setkey(x[, c(k = 1, .SD)], k)[y[,c(k = 1, .SD)], 
               allow.cartesian = TRUE][, k := NULL], 
       a, c) 
    temp <- temp[setkey(proportion, a, c)][, prop := prop/.N, by = .(a, c)] 
    indexes <- temp[, .I[sample(.N, 5, replace = T, prob = prop)], by = a] 
    indexes <- indexes[[2]] 
    temp[indexes] 
} 

benchmark(myFunction(x, y, proportion), myFunction2(x, y, proportion), 
      replications = 5, 
      columns = c("test", "replications", "elapsed", "relative", 
         "user.self", "sys.self")) 

          test replications elapsed relative user.self sys.self 
1 myFunction(x, y, proportion)   5 6.61 1.064  6.23  0.36 
2 myFunction2(x, y, proportion)   5 6.21 1.000  5.71  0.26 

Chúng tôi có thể thấy cải thiện tốc độ biên.

+0

Tôi đã làm một cái gì đó tương tự. Tôi nên cập nhật câu hỏi. Bước mà tôi đã sử dụng là 'selected_pairs <- temp [temp [,. (B = mẫu (b, 5, thay thế = FALSE, prob = prop)), bởi = a], on = c (" a ", "b")] 'chạy so sánh với hàm của bạn. Tôi sẽ chấp nhận câu trả lời của bạn nhưng nếu ai đó có thể giúp tôi tiết kiệm bộ nhớ vì đó là một vấn đề khác mà tôi đang giải quyết ngay bây giờ. –

+0

@AGore Bạn có gặp vấn đề về bộ nhớ chính xác trong hoạt động này không? Dữ liệu và RAM của bạn lớn đến mức nào? Bởi vì tôi không chạy trong bất kỳ. Có thể một số dữ liệu giảm có thể được thực hiện trước. – minem

+0

Tập dữ liệu 'x' và' y' xấp xỉ 5 Gb và 2 Gb resp. Việc kết nối chéo tạo ra đầu ra xấp xỉ 12 Gb. Sản lượng cuối cùng (do lấy mẫu) là khoảng 6 Gb. Tôi có RAM 16 Gb. Tôi không thể tìm ra nơi tôi có thể làm giảm dữ liệu. –

Các vấn đề liên quan