2017-07-30 27 views
6

Tôi có khung dữ liệu sau và ý định của tôi là tìm tất cả các ID, có USAGE khác nhau nhưng cùng TYPE.multidplyr và group_by() và lọc()

ID <- rep(1:4, each=3) 
USAGE <- c("private","private","private","private", 
"taxi","private","taxi","taxi","taxi","taxi","private","taxi") 
TYPE <- c("VW","VW","VW","VW","MER","VW","VW","VW","VW","VW","VW","VW") 
df <- data.frame(ID,USAGE,TYPE) 

Nếu tôi chạy

df %>% group_by(ID, TYPE) %>% filter(n_distinct(USAGE)>1) 

tôi nhận được kết quả mong muốn. Nhưng khung dữ liệu ban đầu của tôi có> 2 triệu hàng. Vì vậy, tôi muốn sử dụng tất cả các lõi của tôi trong hoạt động này.

Tôi đã thử mã này với multidplyr:

f1 <- partition(df, ID) 
f2 <- f1 %>% group_by(ID, TYPE) %>% filter(n_distinct(USAGE)>1) 
f3 <- collect(f2) 

Nhưng sau đó được thông báo sau xuất hiện:

Warning message: group_indices_.grouped_df ignores extra arguments 

sau

f1 <- partition(df, ID) 

Error in checkForRemoteErrors(lapply(cl, recvResult)) : 
    4 nodes produced errors; first error: Evaluation error: object 'f1' not found. 

sau

f2 <- f1%>% group_by(ID, TYPE) %>% filter(f1, n_distinct(USAGE)>1) 

Điều gì sẽ là cách chính xác để thực hiện toàn bộ hoạt động vào multidplyr? Cảm ơn rất nhiều.

Trả lời

2

Bạn nên bao gồm tất cả các biến nhóm trong cuộc gọi đến partition(). Bằng cách đó, mỗi lõi có tất cả các dữ liệu cần thiết để thực hiện một phép tính cho một nhóm nhất định.

library(tidyverse) 
library(multidplyr) 

fast <- df %>% 
    partition(ID, TYPE) %>% 
    group_by(ID, TYPE) %>% 
    filter(n_distinct(USAGE) > 1) %>% 
    collect() 

Xác

Bạn vẫn sẽ nhận được cảnh báo về group_indices, nhưng kết quả đều giống nhau như là phương pháp gốc dplyr.

slow <- df %>% 
    group_by(ID, TYPE) %>% 
    filter(n_distinct(USAGE) > 1) 

fast == slow 
     ID USAGE TYPE 
#[1,] TRUE TRUE TRUE 
#[2,] TRUE TRUE TRUE 
#[3,] TRUE TRUE TRUE 

Benchmarking

Bây giờ câu hỏi lớn: là nó nhanh hơn? Xác định cluster cho phép chúng tôi đảm bảo rằng chúng tôi đang sử dụng tất cả các lõi.

library(microbenchmark) 
library(parallel) 

cluster <- create_cluster(cores = detectCores()) 

fast_func <- function(df) { 
    df %>% 
    partition(ID, TYPE, cluster = cluster) %>% 
    group_by(ID, TYPE) %>% 
    filter(n_distinct(USAGE) > 1) %>% 
    collect() 
} 

slow_func <- function(df) { 
    slow <- df %>% 
    group_by(ID, TYPE) %>% 
    filter(n_distinct(USAGE) > 1) 
} 

microbenchmark(fast_func(df), slow_func(df)) 
# Unit: milliseconds 
# expr  min  lq  mean median  uq  max neval cld 
# fast_func(df) 41.360358 47.529695 55.806609 50.529851 61.459433 133.53045 100 b 
# slow_func(df) 4.717761 6.974897 9.333049 7.796686 8.468594 49.51916 100 a 

Sử dụng xử lý song song thực sự là chậm trong trường hợp này. Việc chạy trung bình cho fast_func mất 56 mili giây thay vì 9. Đó là do chi phí liên quan đến việc quản lý luồng dữ liệu trên các cụm. Nhưng bạn nói dữ liệu của bạn có hàng triệu hàng, vì vậy hãy thử điều đó.

# Embiggen the data 
df <- df[rep(seq_len(nrow(df)), each=2000000),] %>% tbl_df() 

microbenchmark(fast_func(df), slow_func(df)) 
# Unit: seconds 
# expr  min  lq  mean median  uq  max neval cld 
# fast_func(df) 43.067089 43.781144 50.754600 49.440864 55.308355 65.499095 10 b 
# slow_func(df) 1.741674 2.550008 3.529607 3.246665 3.983452 7.214484 10 a 

Với tập dữ liệu khổng lồ, fast_func vẫn chậm hơn! Có những lúc chạy song song sẽ tiết kiệm rất nhiều thời gian, nhưng một bộ lọc nhóm đơn giản không nhất thiết phải là một trong số chúng.

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