Saya memiliki kebiasaan menggabung tugas-tugas serupa menjadi satu baris. Sebagai contoh, jika saya perlu menyaring a, bdan cdalam tabel data, saya akan menempatkan mereka bersama-sama dalam satu []dengan ANDs. Kemarin, saya perhatikan bahwa dalam kasus khusus saya ini adalah filter chaining yang sangat lambat dan diuji. Saya telah memasukkan contoh di bawah ini.
Pertama, saya seed generator nomor acak, memuat data.table , dan membuat kumpulan data dummy.
# Set RNG seed
set.seed(-1)
# Load libraries
library(data.table)
# Create data table
dt <- data.table(a = sample(1:1000, 1e7, replace = TRUE),
b = sample(1:1000, 1e7, replace = TRUE),
c = sample(1:1000, 1e7, replace = TRUE),
d = runif(1e7))
Selanjutnya, saya mendefinisikan metode saya. Rantai pendekatan pertama menyaring bersama. ANDs kedua menyaring bersama.
# Chaining method
chain_filter <- function(){
dt[a %between% c(1, 10)
][b %between% c(100, 110)
][c %between% c(750, 760)]
}
# Anding method
and_filter <- function(){
dt[a %between% c(1, 10) & b %between% c(100, 110) & c %between% c(750, 760)]
}
Di sini, saya periksa mereka memberikan hasil yang sama.
# Check both give same result
identical(chain_filter(), and_filter())
#> [1] TRUE
Akhirnya, saya membandingkannya.
# Benchmark
microbenchmark::microbenchmark(chain_filter(), and_filter())
#> Unit: milliseconds
#> expr min lq mean median uq max
#> chain_filter() 25.17734 31.24489 39.44092 37.53919 43.51588 78.12492
#> and_filter() 92.66411 112.06136 130.92834 127.64009 149.17320 206.61777
#> neval cld
#> 100 a
#> 100 b
Dibuat pada 2019-10-25 oleh paket reprex (v0.3.0)
Dalam hal ini, perangkaian mengurangi waktu lari sekitar 70%. Mengapa demikian? Maksudku, apa yang terjadi di bawah tenda data? Saya belum melihat adanya peringatan untuk tidak menggunakan &, jadi saya terkejut bahwa perbedaannya sangat besar. Dalam kedua kasus mereka mengevaluasi kondisi yang sama, sehingga seharusnya tidak menjadi perbedaan. Dalam kasus AND, &adalah operator cepat dan kemudian hanya perlu memfilter tabel data sekali (yaitu, menggunakan vektor logis yang dihasilkan dari ANDs), sebagai lawan untuk memfilter tiga kali dalam chaining case.
Pertanyaan bonus
Apakah prinsip ini berlaku untuk operasi tabel data secara umum? Apakah tugas modularising selalu merupakan strategi yang lebih baik?
basepengamatan serupa dengan vektor dengan melakukan hal berikut: chain_vec <- function() { x <- which(a < .001); x[which(b[x] > .999)] }dan and_vec <- function() { which(a < .001 & b > .999) }. (Di mana adan bmerupakan vektor dengan panjang yang sama dari runif- saya gunakan n = 1e7untuk cutoff ini).