ฉันติดนิสัยที่คล้ายกันในการทำงานเป็นแถวเดียว ตัวอย่างเช่นถ้าฉันต้องกรองa, bและcในตารางข้อมูลผมจะนำพวกเขาเข้าด้วยกันในหนึ่ง[]กับ ANDs เมื่อวานนี้ฉันสังเกตเห็นว่าในกรณีของฉันนี่เป็นตัวกรองช้าและเหลือเชื่อแทนการทดสอบ ฉันได้รวมตัวอย่างด้านล่างแล้ว
ก่อนอื่นฉันจะสร้างตัวสร้างตัวเลขสุ่มโหลดdata.tableและสร้างชุดข้อมูลจำลอง
# 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))
ต่อไปฉันจะกำหนดวิธีการของฉัน วิธีแรกโซ่กรองด้วยกัน อันที่สอง ANDs ตัวกรองเข้าด้วยกัน
# 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)]
}
ที่นี่ฉันตรวจสอบพวกเขาให้ผลลัพธ์เดียวกัน
# Check both give same result
identical(chain_filter(), and_filter())
#> [1] TRUE
ในที่สุดฉันมาตรฐานพวกเขา
# 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 โดยแพ็คเกจ reprex (v0.3.0)
ในกรณีนี้การผูกมัดจะลดเวลาทำงานประมาณ 70% ทำไมเป็นกรณีนี้ ฉันหมายถึงสิ่งที่เกิดขึ้นภายใต้ประทุนในตารางข้อมูล? ฉันไม่ได้เห็นคำเตือนใด ๆ เกี่ยวกับการใช้&ดังนั้นฉันแปลกใจว่าความแตกต่างใหญ่มาก ในทั้งสองกรณีพวกเขาประเมินเงื่อนไขเดียวกันดังนั้นจึงไม่ควรแตกต่างกัน ในกรณี AND &เป็นตัวดำเนินการด่วนและจากนั้นจะต้องกรองตารางข้อมูลเพียงครั้งเดียว (เช่นการใช้เวกเตอร์แบบลอจิคัลที่เกิดจาก ANDs) ซึ่งตรงข้ามกับการกรองสามครั้งในกรณีการผูกมัด
คำถามโบนัส
หลักการนี้มีไว้สำหรับการทำงานของตารางข้อมูลโดยทั่วไปหรือไม่? ภารกิจการทำให้เป็นโมดูลเป็นกลยุทธ์ที่ดีกว่าเสมอหรือไม่?
baseสังเกตกับเวกเตอร์โดยการทำต่อไปนี้: และchain_vec <- function() { x <- which(a < .001); x[which(b[x] > .999)] } and_vec <- function() { which(a < .001 & b > .999) }(ที่ไหนaและbมีเวกเตอร์ที่มีความยาวเท่ากันจากrunif- ฉันใช้n = 1e7สำหรับการตัดยอดเหล่านี้)