Gambaran
Saya relatif akrab dengan data.table
, tidak begitu banyak dengan dplyr
. Saya telah membaca beberapa dplyr
sketsa dan contoh yang muncul di SO, dan sejauh ini kesimpulan saya adalah:
data.table
dandplyr
sebanding dalam kecepatan, kecuali ketika ada banyak (yaitu> 10-100K) kelompok, dan dalam beberapa keadaan lain (lihat tolok ukur di bawah)dplyr
memiliki sintaks yang lebih mudah diaksesdplyr
abstrak (atau akan) potensi interaksi DB- Ada beberapa perbedaan fungsionalitas kecil (lihat "Contoh / Penggunaan" di bawah)
Dalam pikiran saya 2. tidak menanggung banyak beban karena saya cukup akrab dengannya data.table
, meskipun saya mengerti bahwa bagi pengguna baru keduanya akan menjadi faktor besar. Saya ingin menghindari argumen tentang mana yang lebih intuitif, karena itu tidak relevan untuk pertanyaan spesifik saya yang diajukan dari sudut pandang seseorang yang sudah terbiasa data.table
. Saya juga ingin menghindari diskusi tentang bagaimana "lebih intuitif" mengarah pada analisis yang lebih cepat (tentu saja benar, tetapi sekali lagi, bukan yang paling saya minati di sini).
Pertanyaan
Yang ingin saya ketahui adalah:
- Apakah ada tugas analitis yang jauh lebih mudah untuk dikodekan dengan satu atau paket lain untuk orang yang akrab dengan paket (yaitu beberapa kombinasi penekanan tombol yang diperlukan vs tingkat esoterisme yang diperlukan, di mana kurang dari masing-masing adalah hal yang baik).
- Apakah ada tugas analitik yang dilakukan secara substansial (yaitu lebih dari 2x) lebih efisien dalam satu paket vs yang lain.
Satu pertanyaan SO baru-baru ini membuat saya berpikir tentang ini sedikit lebih, karena sampai saat itu saya tidak berpikir dplyr
akan menawarkan banyak hal di luar apa yang sudah bisa saya lakukan data.table
. Ini dplyr
solusinya (data di akhir Q):
dat %.%
group_by(name, job) %.%
filter(job != "Boss" | year == min(year)) %.%
mutate(cumu_job2 = cumsum(job2))
Yang jauh lebih baik daripada upaya hack saya pada data.table
solusi. Yang mengatakan, data.table
solusi yang baik juga cukup bagus (terima kasih Jean-Robert, Arun, dan perhatikan di sini saya lebih suka pernyataan tunggal daripada solusi yang paling optimal):
setDT(dat)[,
.SD[job != "Boss" | year == min(year)][, cumjob := cumsum(job2)],
by=list(id, job)
]
Sintaksis untuk yang terakhir mungkin tampak sangat esoteris, tetapi sebenarnya cukup mudah jika Anda terbiasa data.table
(yaitu tidak menggunakan beberapa trik yang lebih esoteris).
Idealnya yang ingin saya lihat adalah beberapa contoh yang baik jika dplyr
atau data.table
caranya jauh lebih ringkas atau berkinerja lebih baik.
Contohnya
Pemakaiandplyr
tidak mengizinkan operasi yang dikelompokkan yang mengembalikan jumlah baris sewenang-wenang (dari pertanyaan eddi , perhatikan: sepertinya ini akan diimplementasikan dalam dplyr 0.5 , juga, @beginneR menunjukkan potensi penyelesaian dengan menggunakando
jawaban untuk pertanyaan @ eddi).data.table
mendukung rolling bergabung (terima kasih @dholstius) serta tumpang tindih bergabungdata.table
secara internal mengoptimalkan ekspresi bentukDT[col == value]
atauDT[col %in% values]
untuk kecepatan melalui pengindeksan otomatis yang menggunakan pencarian biner saat menggunakan sintaks R dasar yang sama. Lihat di sini untuk detail lebih lanjut dan tolok ukur kecil.dplyr
menawarkan versi evaluasi fungsi standar (misalnyaregroup
,summarize_each_
) yang dapat menyederhanakan penggunaan programatikdplyr
(perhatikan penggunaan programatikdata.table
pasti dimungkinkan, hanya memerlukan beberapa pemikiran, penggantian / penawaran, dll, setidaknya setahu saya)
- Saya menjalankan tolok ukur saya sendiri dan menemukan kedua paket tersebut dapat dibandingkan dalam analisis gaya "split apply menggabungkan", kecuali ketika ada sejumlah besar kelompok (> 100K) di mana titik
data.table
menjadi jauh lebih cepat. - @Arun menjalankan beberapa tolok ukur pada gabungan , menunjukkan bahwa
data.table
skala lebih baik daripadadplyr
jumlah grup yang bertambah (diperbarui dengan perangkat tambahan terbaru di kedua paket dan versi terbaru R). Juga, suatu tolok ukur ketika mencoba untuk mendapatkan nilai unik memilikidata.table
~ 6x lebih cepat. - (Tidak diverifikasi) memiliki
data.table
75% lebih cepat pada versi yang lebih besar dari grup / apply / sort sementaradplyr
40% lebih cepat pada yang lebih kecil ( pertanyaan SO lain dari komentar , terima kasih danas). - Matt, penulis utama
data.table
, telah membandingkan operasi pengelompokandata.table
,dplyr
dan pythonpandas
hingga 2 miliar baris (~ 100GB dalam RAM) . - Sebuah patokan yang lebih tua di 80K kelompok memiliki
data.table
~ 8x lebih cepat
Data
Ini adalah contoh pertama yang saya tunjukkan di bagian pertanyaan.
dat <- structure(list(id = c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L,
2L, 2L, 2L, 2L, 2L, 2L), name = c("Jane", "Jane", "Jane", "Jane",
"Jane", "Jane", "Jane", "Jane", "Bob", "Bob", "Bob", "Bob", "Bob",
"Bob", "Bob", "Bob"), year = c(1980L, 1981L, 1982L, 1983L, 1984L,
1985L, 1986L, 1987L, 1985L, 1986L, 1987L, 1988L, 1989L, 1990L,
1991L, 1992L), job = c("Manager", "Manager", "Manager", "Manager",
"Manager", "Manager", "Boss", "Boss", "Manager", "Manager", "Manager",
"Boss", "Boss", "Boss", "Boss", "Boss"), job2 = c(1L, 1L, 1L,
1L, 1L, 1L, 0L, 0L, 1L, 1L, 1L, 0L, 0L, 0L, 0L, 0L)), .Names = c("id",
"name", "year", "job", "job2"), class = "data.frame", row.names = c(NA,
-16L))
dplyr
dan data.table
tim bekerja pada tolok ukur, jadi jawabannya akan ada di beberapa titik. # 2 (sintaksis) imO benar-benar salah, tetapi jelas menjelajah ke wilayah opini, jadi saya memilih untuk menutup juga.
(d)plyr
ukuran 0
dplyr
dan plyr
berkaitan dengan sintaks dan pada dasarnya adalah alasan utama mengapa saya tidak suka sintaks mereka, adalah bahwa saya harus belajar terlalu banyak (baca lebih dari 1) fungsi tambahan (dengan nama yang masih tidak masuk akal bagi saya), ingat apa yang mereka lakukan, argumen apa yang mereka ambil, dll. Itu selalu merupakan perubahan besar bagi saya dari plyr-filsafat.
.SD
.). [Serius] Saya pikir ini adalah perbedaan desain yang sah yang akan menarik bagi orang yang berbeda
dplyr
adalah:as.data.table(dat)[, .SD[job != "Boss" | year == min(year)][, cumjob := cumsum(job2)], by = list(name, job)]