Misalnya (tidak yakin apakah contoh yang paling representatif):
N <- 1e6
d1 <- data.frame(x=sample(N,N), y1=rnorm(N))
d2 <- data.frame(x=sample(N,N), y2=rnorm(N))
Inilah yang saya dapatkan sejauh ini:
d <- merge(d1,d2)
# 7.6 sec
library(plyr)
d <- join(d1,d2)
# 2.9 sec
library(data.table)
dt1 <- data.table(d1, key="x")
dt2 <- data.table(d2, key="x")
d <- data.frame( dt1[dt2,list(x,y1,y2=dt2$y2)] )
# 4.9 sec
library(sqldf)
sqldf()
sqldf("create index ix1 on d1(x)")
sqldf("create index ix2 on d2(x)")
d <- sqldf("select * from d1 inner join d2 on d1.x=d2.x")
sqldf()
# 17.4 sec
performance
r
join
merge
data.table
datamurf
sumber
sumber
Jawaban:
Pendekatan kecocokan berfungsi jika ada kunci unik dalam bingkai data kedua untuk setiap nilai kunci di yang pertama. Jika ada duplikat pada data frame kedua maka pendekatan match and merge tidak sama. Pertandingan, tentu saja, lebih cepat karena tidak terlalu banyak. Secara khusus tidak pernah mencari kunci duplikat. (dilanjutkan setelah kode)
Dalam kode sqldf yang diposting di pertanyaan, mungkin tampak bahwa indeks digunakan pada dua tabel tetapi, pada kenyataannya, mereka ditempatkan pada tabel yang ditimpa sebelum pemilihan sql berjalan dan itu, sebagian, menjelaskan mengapa ini sangat lambat. Ide dari sqldf adalah bahwa bingkai data di sesi R Anda merupakan basis data, bukan tabel di sqlite. Jadi, setiap kali kode merujuk ke nama tabel yang tidak memenuhi syarat, kode itu akan mencari di ruang kerja R Anda untuk itu - bukan di database utama sqlite. Jadi pernyataan pemilihan yang ditampilkan membaca d1 dan d2 dari ruang kerja ke dalam database utama sqlite mengalahkan database yang ada dengan indeks. Akibatnya, ia bergabung tanpa indeks. Jika Anda ingin menggunakan versi d1 dan d2 yang ada di database utama sqlite, Anda harus merujuknya sebagai main.d1 dan main. d2 dan bukan sebagai d1 dan d2. Selain itu, jika Anda mencoba membuatnya berjalan secepat mungkin, perhatikan bahwa gabungan sederhana tidak dapat menggunakan indeks pada kedua tabel sehingga Anda dapat menghemat waktu untuk membuat salah satu indeks. Pada kode di bawah ini kami menggambarkan poin-poin ini.
Perlu diperhatikan bahwa komputasi yang tepat dapat membuat perbedaan besar pada paket mana yang tercepat. Misalnya, kami melakukan penggabungan dan agregat di bawah ini. Kami melihat bahwa hasilnya hampir terbalik untuk keduanya. Dalam contoh pertama dari tercepat hingga paling lambat kita mendapatkan: data.table, plyr, merge dan sqldf sedangkan pada contoh kedua sqldf, aggregate, data.table dan plyr - hampir kebalikan dari yang pertama. Pada contoh pertama, sqldf 3x lebih lambat dari data.table dan yang kedua 200x lebih cepat dari plyr dan 100 kali lebih cepat dari data.table. Di bawah ini kami menunjukkan kode input, waktu keluaran untuk penggabungan dan waktu keluaran untuk agregat. Perlu juga dicatat bahwa sqldf didasarkan pada database dan karena itu dapat menangani objek yang lebih besar dari yang dapat ditangani R (jika Anda menggunakan argumen dbname dari sqldf) sementara pendekatan lain terbatas pada pemrosesan di memori utama. Kami juga telah mengilustrasikan sqldf dengan sqlite tetapi juga mendukung database H2 dan PostgreSQL juga.
Keluaran dari dua panggilan benchmark yang membandingkan kalkulasi penggabungan adalah:
Keluaran dari panggilan tolok ukur yang membandingkan penghitungan agregat adalah:
sumber
132 detik yang dilaporkan dalam hasil Gabor
data.table
sebenarnya adalah fungsi basis waktucolMeans
dancbind
(alokasi memori dan penyalinan diinduksi dengan menggunakan fungsi tersebut). Ada cara penggunaan yang baik dan burukdata.table
juga.Harap dicatat bahwa saya tidak tahu plyr dengan baik jadi harap periksa dengan Hadley sebelum mengandalkan
plyr
waktu di sini. Perhatikan juga bahwadata.table
do termasuk waktu untuk mengkonversidata.table
dan mengatur kunci, untuk jarak jauh.Jawaban ini telah diperbarui sejak jawaban asli pada bulan Desember 2010. Hasil benchmark sebelumnya ada di bawah. Silakan lihat riwayat revisi jawaban ini untuk melihat apa yang berubah.
sumber
.Internal
panggilan dalam paket CRAN, lihat Kebijakan Repositori CRAN .data.table
secara otomatis dioptimalkanmean
sekarang (tanpa menelepon secara.Internal
internal).for
loop, itu bagus. Bisakah Anda menambahkan lebih banyak info tentang "analisis SEM" ke masalah itu? Misalnya saya menebak bahwa SEM = Scanning electron microscope? Mengetahui lebih banyak tentang aplikasi membuatnya lebih menarik bagi kami dan membantu kami memprioritaskan.Untuk tugas sederhana (nilai unik di kedua sisi gabungan) saya menggunakan
match
:Ini jauh lebih cepat daripada menggabungkan (di mesin saya 0,13 detik hingga 3,37 detik).
Waktu saya:
merge
: 3.32splyr
: 0.84smatch
: 0,12 dsumber
Saya pikir akan menarik untuk memposting patokan dengan dplyr dalam campuran: (memiliki banyak hal yang berjalan)
Baru saja menambahkan:
dan atur data untuk dplyr dengan tabel data:
Diperbarui: Saya menghapus data.tableBad dan plyr dan hanya RStudio open (i7, 16GB ram).
Dengan data.table 1.9 dan dplyr dengan data frame:
Dengan data.table 1.9 dan dplyr dengan tabel data:
Untuk konsistensi berikut ini asli dengan all dan data.table 1.9 dan dplyr menggunakan tabel data:
Saya pikir data ini terlalu kecil untuk data.table dan dplyr baru :)
Kumpulan data yang lebih besar:
Butuh sekitar 10-13GB ram hanya untuk menyimpan data sebelum menjalankan benchmark.
Hasil:
Mencoba 1 miliar tapi meledakkan ram. 32GB akan menanganinya tidak masalah.
[Edit oleh Arun] (dotcomken, dapatkah Anda menjalankan kode ini dan menempelkan hasil benchmarking Anda? Terima kasih).
Sesuai permintaan Arun di sini output dari apa yang Anda berikan kepada saya untuk dijalankan:
Maaf atas kebingungannya, larut malam menghampiri saya.
Menggunakan dplyr dengan bingkai data tampaknya menjadi cara yang kurang efisien untuk memproses ringkasan. Apakah metode ini untuk membandingkan fungsionalitas yang tepat dari data.table dan dplyr dengan metode struktur datanya disertakan? Saya hampir lebih suka memisahkan itu karena sebagian besar data perlu dibersihkan sebelum kita group_by atau membuat data.table. Ini bisa menjadi masalah selera tetapi saya pikir bagian terpenting adalah seberapa efisien data dapat dimodelkan.
sumber
Dengan menggunakan fungsi penggabungan dan parameter opsionalnya:
Inner join: merge (df1, df2) akan bekerja untuk contoh ini karena R secara otomatis menggabungkan frame dengan nama variabel umum, tetapi Anda kemungkinan besar ingin menentukan merge (df1, df2, by = "CustomerId") untuk memastikan bahwa Anda cocok hanya pada bidang yang Anda inginkan. Anda juga dapat menggunakan parameter by.x dan by.y jika variabel yang cocok memiliki nama yang berbeda dalam bingkai data yang berbeda.
sumber