Benzer görevleri tek bir hatta toparlama alışkanlığım var. Örneğin, filtrelemem gerekirse a,b , ve cbir veri tablosunda, ben birinde onları biraraya koyacağım []Eleştiri ile. Dün, özel durumumda bunun inanılmaz derecede yavaş olduğunu ve bunun yerine zincirleme filtrelerini test ettiğini fark ettim. Aşağıda bir örnek ekledim.
İlk olarak, rastgele sayı üretecini tohumluyorum , data.table yüklüyorum ve sahte bir veri kümesi oluşturuyorum.
# 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))
Sonra, yöntemlerimi tanımlarım. İlk yaklaşım, filtreleri birlikte zincirler. İkincisi VE filtreleri birlikte.
# 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)]
}
Burada, aynı sonuçları verdiklerini kontrol ediyorum.
# Check both give same result
identical(chain_filter(), and_filter())
#> [1] TRUE
Sonunda, onları karşılaştırıyorum.
# 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
2019-10-25 tarihinde tarafından oluşturuldu reprex paketi (v0.3.0)
Bu durumda zincirleme, çalışma süresini yaklaşık% 70 oranında azaltır. Neden böyle? Yani, veri tablosunda kaputun altında neler oluyor? Kullanmaya karşı herhangi bir uyarı görmedim& , bu yüzden farkın çok büyük olduğuna şaşırdım. Her iki durumda da aynı koşulları değerlendirirler, bu yüzden bir fark olmamalıdır. AND durumunda, &hızlı bir operatördür ve daha sonra, zincirleme durumunda üç kez filtrelemenin aksine, veri tablosunu sadece bir kez filtrelemek zorundadır (yani, AND'lerden kaynaklanan mantıksal vektörü kullanarak).
Bonus soru
Bu ilke genel olarak veri tablosu işlemleri için geçerli midir? Modülerleştirme görevleri her zaman daha iyi bir strateji midir?
base, aşağıdakileri yaparak vektörlerle benzer bir gözlem yapabilirsiniz : chain_vec <- function() { x <- which(a < .001); x[which(b[x] > .999)] }ve and_vec <- function() { which(a < .001 & b > .999) }. (nerede ave baynı uzunlukta vektörler runif- Ben n = 1e7bu kesikler için kullanılır ).