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)
DF1 = data.frame(a = c(1, 1, 2, 2), b = 1:4)
DF2 = data.frame(b = c(1, 2, 3, 3, 4), c = letters[1:5])
merge(DF1, DF2)
b a c
1 1 1 a
2 2 1 b
3 3 2 c
4 3 2 d
5 4 2 e
DF1$c = DF2$c[match(DF1$b, DF2$b)]
DF1$c
[1] a b c e
Levels: a b c d e
> DF1
a b c
1 1 1 a
2 1 2 b
3 2 3 c
4 2 4 e
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.
library(plyr)
library(data.table)
library(sqldf)
set.seed(123)
N <- 1e5
d1 <- data.frame(x=sample(N,N), y1=rnorm(N))
d2 <- data.frame(x=sample(N,N), y2=rnorm(N))
g1 <- sample(1:1000, N, replace = TRUE)
g2<- sample(1:1000, N, replace = TRUE)
d <- data.frame(d1, g1, g2)
library(rbenchmark)
benchmark(replications = 1, order = "elapsed",
merge = merge(d1, d2),
plyr = join(d1, d2),
data.table = {
dt1 <- data.table(d1, key = "x")
dt2 <- data.table(d2, key = "x")
data.frame( dt1[dt2,list(x,y1,y2=dt2$y2)] )
},
sqldf = sqldf(c("create index ix1 on d1(x)",
"select * from main.d1 join d2 using(x)"))
)
set.seed(123)
N <- 1e5
g1 <- sample(1:1000, N, replace = TRUE)
g2<- sample(1:1000, N, replace = TRUE)
d <- data.frame(x=sample(N,N), y=rnorm(N), g1, g2)
benchmark(replications = 1, order = "elapsed",
aggregate = aggregate(d[c("x", "y")], d[c("g1", "g2")], mean),
data.table = {
dt <- data.table(d, key = "g1,g2")
dt[, colMeans(cbind(x, y)), by = "g1,g2"]
},
plyr = ddply(d, .(g1, g2), summarise, avx = mean(x), avy=mean(y)),
sqldf = sqldf(c("create index ix on d(g1, g2)",
"select g1, g2, avg(x), avg(y) from main.d group by g1, g2"))
)
Keluaran dari dua panggilan benchmark yang membandingkan kalkulasi penggabungan adalah:
Joining by: x
test replications elapsed relative user.self sys.self user.child sys.child
3 data.table 1 0.34 1.000000 0.31 0.01 NA NA
2 plyr 1 0.44 1.294118 0.39 0.02 NA NA
1 merge 1 1.17 3.441176 1.10 0.04 NA NA
4 sqldf 1 3.34 9.823529 3.24 0.04 NA NA
Keluaran dari panggilan tolok ukur yang membandingkan penghitungan agregat adalah:
test replications elapsed relative user.self sys.self user.child sys.child
4 sqldf 1 2.81 1.000000 2.73 0.02 NA NA
1 aggregate 1 14.89 5.298932 14.89 0.00 NA NA
2 data.table 1 132.46 47.138790 131.70 0.08 NA NA
3 plyr 1 212.69 75.690391 211.57 0.56 NA NA