Không có câu trả lời đơn giản / dễ hiểu vì triết lý của cả hai gói này khác nhau ở một số khía cạnh nhất định. Vì vậy, một số thỏa hiệp là khó tránh khỏi. Dưới đây là một số mối quan tâm bạn có thể cần giải quyết / xem xét.
Các hoạt động liên quan đến i
(== filter()
và slice()
trong dplyr)
Giả sử DT
với giả sử 10 cột. Hãy xem xét các biểu thức data.table sau:
DT[a > 1, .N]
DT[a > 1, mean(b), by=.(c, d)]
(1) cho biết số hàng trong DT
cột nơi a > 1
. (2) trả về mean(b)
được nhóm theo c,d
cho cùng một biểu thức trong i
(1).
Các dplyr
biểu thức thường được sử dụng sẽ là:
DT %>% filter(a > 1) %>% summarise(n())
DT %>% filter(a > 1) %>% group_by(c, d) %>% summarise(mean(b))
Rõ ràng, mã data.table ngắn hơn. Ngoài ra chúng cũng hiệu quả hơn về bộ nhớ 1 . Tại sao? Bởi vì trong cả (3) và (4), filter()
trả về các hàng cho tất cả 10 cột trước, khi ở (3) chúng ta chỉ cần số hàng và trong (4), chúng ta chỉ cần các cột b, c, d
cho các hoạt động kế tiếp. Để khắc phục điều này, chúng ta phải select()
cột apriori:
DT %>% select(a) %>% filter(a > 1) %>% summarise(n())
DT %>% select(a,b,c,d) %>% filter(a > 1) %>% group_by(c,d) %>% summarise(mean(b))
Điều cần thiết là làm nổi bật sự khác biệt chính về triết học giữa hai gói:
Trong đó data.table
, chúng tôi muốn giữ các thao tác liên quan này lại với nhau, và điều đó cho phép xem xét j-expression
(từ cùng một lệnh gọi hàm) và nhận ra rằng không cần bất kỳ cột nào trong (1). Biểu thức trong i
được tính toán và .N
chỉ là tổng của vectơ logic đó cung cấp số hàng; toàn bộ tập hợp con không bao giờ được nhận ra. Trong (2), chỉ cột b,c,d
được thực hiện trong tập hợp con, các cột khác bị bỏ qua.
Nhưng trong dplyr
, triết lý là phải có một chức năng làm chính xác một điều tốt . Không có (ít nhất là hiện tại) không có cách nào để biết liệu hoạt động sau đó có filter()
cần tất cả các cột mà chúng tôi đã lọc hay không. Bạn sẽ cần phải suy nghĩ trước nếu muốn thực hiện những công việc như vậy một cách hiệu quả. Cá nhân tôi thấy nó phản cảm trong trường hợp này.
Lưu ý rằng trong (5) và (6), chúng tôi vẫn đặt cột con a
mà chúng tôi không yêu cầu. Nhưng tôi không chắc làm thế nào để tránh điều đó. Nếu filter()
hàm có một đối số để chọn các cột để trả về, chúng ta có thể tránh được vấn đề này, nhưng sau đó hàm sẽ không chỉ thực hiện một tác vụ (cũng là một lựa chọn thiết kế dplyr).
Chỉ định phụ bằng tham chiếu
dplyr sẽ không bao giờ cập nhật bằng cách tham khảo. Đây là một khác biệt lớn (triết học) giữa hai gói.
Ví dụ, trong data.table, bạn có thể thực hiện:
DT[a %in% some_vals, a := NA]
cập nhật cột a
bằng cách tham chiếu chỉ trên những hàng thỏa mãn điều kiện. Hiện tại, dplyr sao chép sâu toàn bộ data.table trong nội bộ để thêm một cột mới. @BrodieG đã đề cập đến điều này trong câu trả lời của anh ấy.
Nhưng bản sao sâu có thể được thay thế bằng bản sao nông khi FR # 617 được triển khai. Cũng có liên quan: dplyr: FR # 614 . Tuy nhiên, lưu ý rằng cột bạn sửa đổi sẽ luôn được sao chép (do đó, bộ nhớ chậm hơn / kém hiệu quả hơn). Sẽ không có cách nào để cập nhật các cột bằng cách tham chiếu.
Các chức năng khác
Trong data.table, bạn có thể tổng hợp trong khi tham gia và điều này dễ hiểu hơn và hiệu quả về bộ nhớ vì kết quả nối trung gian không bao giờ được thực hiện. Kiểm tra bài đăng này cho một ví dụ. Bạn không thể (vào lúc này?) Làm điều đó bằng cú pháp data.table / data.frame của dplyr.
Tính năng kết hợp cuộn của data.table cũng không được hỗ trợ trong cú pháp của dplyr.
Gần đây chúng tôi đã triển khai các phép nối chồng chéo trong data.table để nối trên các phạm vi khoảng thời gian ( đây là một ví dụ ), đây là một hàm riêng biệt foverlaps()
tại thời điểm này và do đó có thể được sử dụng với các toán tử ống (magrittr / pipeR? - chưa bao giờ tôi tự thử).
Nhưng cuối cùng, mục tiêu của chúng tôi là tích hợp nó vào [.data.table
để chúng tôi có thể thu thập các tính năng khác như nhóm, tổng hợp trong khi tham gia, v.v. sẽ có những hạn chế tương tự như đã nêu ở trên.
Kể từ 1.9.4, data.table thực hiện lập chỉ mục tự động bằng cách sử dụng các khóa phụ cho các tập con dựa trên tìm kiếm nhị phân nhanh trên cú pháp R thông thường. Ví dụ: DT[x == 1]
và DT[x %in% some_vals]
sẽ tự động tạo chỉ mục trong lần chạy đầu tiên, chỉ mục này sau đó sẽ được sử dụng trên các tập con liên tiếp từ cùng một cột đến tập con nhanh bằng cách sử dụng tìm kiếm nhị phân. Tính năng này sẽ tiếp tục phát triển. Kiểm tra ý chính này để biết tổng quan ngắn gọn về tính năng này.
Từ cách filter()
được triển khai cho data.tables, nó không tận dụng được tính năng này.
Một tính năng của dplyr là nó cũng cung cấp giao diện cho cơ sở dữ liệu bằng cách sử dụng cùng một cú pháp, điều mà data.table không có vào lúc này.
Vì vậy, bạn sẽ phải cân nhắc những điểm này (và có thể là những điểm khác) và quyết định dựa trên việc liệu những đánh đổi này có thể chấp nhận được với bạn hay không.
HTH
(1) Lưu ý rằng hiệu quả về bộ nhớ sẽ ảnh hưởng trực tiếp đến tốc độ (đặc biệt là khi dữ liệu ngày càng lớn), vì nút cổ chai trong hầu hết các trường hợp là di chuyển dữ liệu từ bộ nhớ chính vào bộ nhớ đệm (và tận dụng dữ liệu trong bộ nhớ đệm càng nhiều càng tốt - giảm bỏ lỡ bộ nhớ cache - để giảm truy cập bộ nhớ chính). Không đi vào chi tiết ở đây.
dplyr
phương pháp cho các bảng dữ liệu, nhưng bảng dữ liệu cũng có phương pháp so sánh riêng của mình