Tidak ada jawaban yang lugas / sederhana karena filosofi kedua paket ini berbeda dalam aspek tertentu. Jadi beberapa kompromi tidak bisa dihindari. Berikut adalah beberapa masalah yang mungkin perlu Anda tangani / pertimbangkan.
Operasi yang melibatkan i
(== filter()
danslice()
dalam dplyr)
Asumsikan DT
dengan katakanlah 10 kolom. Pertimbangkan ekspresi data.table ini:
DT[a > 1, .N]
DT[a > 1, mean(b), by=.(c, d)]
(1) memberikan jumlah baris di DT
mana kolom a > 1
. (2) mengembalikan mean(b)
dikelompokkan oleh c,d
untuk ekspresi yang sama i
seperti (1).
dplyr
Ekspresi yang umum digunakan adalah:
DT %>% filter(a > 1) %>% summarise(n())
DT %>% filter(a > 1) %>% group_by(c, d) %>% summarise(mean(b))
Jelasnya, kode data.table lebih pendek. Selain itu mereka juga lebih hemat memori 1 . Mengapa? Karena di kedua (3) dan (4), filter()
mengembalikan baris untuk semua 10 kolom terlebih dahulu, ketika di (3) kita hanya membutuhkan jumlah baris, dan di (4) kita hanya perlu kolom b, c, d
untuk operasi berturut-turut. Untuk mengatasinya, kita harus select()
kolom 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))
Penting untuk menyoroti perbedaan filosofis utama antara kedua paket:
Di data.table
, kami ingin menjaga operasi terkait ini bersama-sama, dan itu memungkinkan untuk melihat j-expression
(dari pemanggilan fungsi yang sama) dan menyadari bahwa tidak diperlukan kolom apa pun di (1). Ekspresi dalam i
dihitung, dan .N
hanya jumlah dari vektor logika yang memberikan jumlah baris; seluruh bagian tidak pernah terwujud. Dalam (2), hanya kolom b,c,d
yang terwujud dalam subset, kolom lain diabaikan.
Tapi dalam dplyr
, filosofi adalah memiliki fungsi melakukan tepat satu hal dengan baik . Tidak (setidaknya saat ini) tidak ada cara untuk mengetahui apakah operasi setelahnya filter()
membutuhkan semua kolom yang kami filter. Anda harus berpikir jauh ke depan jika ingin melakukan tugas tersebut secara efisien. Saya pribadi merasa kontra-intutitif dalam kasus ini.
Perhatikan bahwa di (5) dan (6), kami masih subset kolom a
yang tidak kami butuhkan. Tapi saya tidak yakin bagaimana menghindarinya. Jikafilter()
fungsi memiliki argumen untuk memilih kolom yang akan dikembalikan, kita dapat menghindari masalah ini, tetapi kemudian fungsi tersebut tidak hanya melakukan satu tugas (yang juga merupakan pilihan desain dplyr).
Sub-tugaskan dengan referensi
dplyr tidak akan pernah diperbarui dengan referensi. Ini adalah perbedaan besar (filosofis) antara kedua paket.
Misalnya, di data.table Anda dapat melakukan:
DT[a %in% some_vals, a := NA]
yang memperbarui kolom a
dengan referensi hanya pada baris-baris yang memenuhi kondisi. Saat ini dplyr deep menyalin seluruh data.table secara internal untuk menambahkan kolom baru. @BrodieG sudah menyebutkan ini dalam jawabannya.
Tetapi salinan dalam dapat diganti dengan salinan dangkal ketika FR # 617 diimplementasikan. Juga relevan: dplyr: FR # 614 . Perhatikan bahwa tetap saja, kolom yang Anda ubah akan selalu disalin (oleh karena itu anak laki-laki lebih lambat / kurang efisien memori). Tidak ada cara untuk memperbarui kolom dengan referensi.
Fungsi lainnya
Dalam data.table, Anda dapat menggabungkan saat bergabung, dan ini lebih mudah dipahami dan hemat memori karena hasil gabungan antara tidak pernah terwujud. Lihat posting ini sebagai contoh. Anda tidak dapat (saat ini?) Melakukan itu menggunakan sintaks data.table / data.frame dplyr.
Fitur rolling join data.table juga tidak didukung dalam sintaks dplyr.
Kami baru-baru ini mengimplementasikan gabungan tumpang tindih di data.table untuk menggabungkan rentang interval ( berikut adalah contoh ), yang merupakan fungsi terpisahfoverlaps()
saat ini, dan oleh karena itu dapat digunakan dengan operator pipa (magrittr / pipeR? - tidak pernah mencobanya sendiri).
Tetapi pada akhirnya, tujuan kami adalah untuk mengintegrasikannya ke dalam [.data.table
sehingga kami dapat memanen fitur lain seperti pengelompokan, menggabungkan saat bergabung, dll .. yang akan memiliki batasan yang sama seperti yang diuraikan di atas.
Sejak 1.9.4, data.table mengimplementasikan pengindeksan otomatis menggunakan kunci sekunder untuk subset berbasis pencarian biner cepat pada sintaks R. Contoh: DT[x == 1]
dan DT[x %in% some_vals]
secara otomatis akan membuat indeks saat pertama kali dijalankan, yang kemudian akan digunakan pada subset berturut-turut dari kolom yang sama ke subset cepat menggunakan pencarian biner. Fitur ini akan terus berkembang. Periksa inti ini untuk gambaran singkat tentang fitur ini.
Dari cara filter()
diimplementasikan untuk data.tables, tidak memanfaatkan fitur ini.
Fitur dplyr adalah ia juga menyediakan antarmuka ke database menggunakan sintaks yang sama, yang saat ini tidak dimiliki data.table.
Jadi, Anda harus mempertimbangkan ini (dan mungkin poin lainnya) dan memutuskan berdasarkan apakah trade-off ini dapat Anda terima.
HTH
(1) Perhatikan bahwa efisiensi memori secara langsung berdampak pada kecepatan (terutama saat data semakin besar), karena hambatan dalam banyak kasus adalah memindahkan data dari memori utama ke cache (dan memanfaatkan data dalam cache sebanyak mungkin - kurangi cache yang hilang - sehingga mengurangi pengaksesan memori utama). Tidak membahas detailnya di sini.
dplyr
metode untuk tabel data, tetapi tabel data juga memiliki metode yang sebanding