gpt4 book ai didi

r - 过滤数据表时链接 ANDing 的性能优势

转载 作者:行者123 更新时间:2023-12-04 01:06:44 26 4
gpt4 key购买 nike

我习惯将类似的任务集中到一行中。例如,如果我需要过滤 a , b , 和 c在数据表中,我将它们放在一个 []与 AND。昨天,我注意到在我的特殊情况下,这非常慢,而是测试了链接过滤器。我在下面提供了一个示例。
首先,我播种随机数生成器,加载 ,并创建一个虚拟数据集。

# 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))
接下来,我定义我的方法。第一种方法将过滤器链接在一起。第二个 AND 将过滤器组合在一起。
# 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 package (v0.3.0)
在这种情况下,链接减少了大约 70% 的运行时间。为什么会这样?我的意思是,数据表的幕后发生了什么?我没有看到任何关于使用 & 的警告,所以我很惊讶差异如此之大。在这两种情况下,他们评估相同的条件,所以这不应该是一个区别。在 AND 情况下, &是一个快速运算符,然后它只需要过滤一次数据表(即,使用 AND 产生的逻辑向量),而不是在链接情况下过滤三次。
奖金问题
这个原则是否适用于一般的数据表操作?模块化任务总是更好的策略吗?

最佳答案

大多数情况下,答案已经在评论中给出:data.table 的“链接方法”。在这种情况下比“anding 方法”更快,因为链接一个接一个地运行条件。随着每一步减小 data.table 的大小下一个要评估的就更少了。 “Anding”每次评估全尺寸数据的条件。

我们可以用一个例子来证明这一点:当单个步骤不减小 data.table 的大小时(即两种方法的检查条件相同):

chain_filter <- function(){
dt[a %between% c(1, 1000) # runs evaluation but does not filter out cases
][b %between% c(1, 1000)
][c %between% c(750, 760)]
}

# Anding method
and_filter <- function(){
dt[a %between% c(1, 1000) & b %between% c(1, 1000) & c %between% c(750, 760)]
}

使用相同的数据,但 bench包,它会自动检查结果是否相同:
res <- bench::mark(
chain = chain_filter(),
and = and_filter()
)
summary(res)
#> # A tibble: 2 x 6
#> expression min median `itr/sec` mem_alloc `gc/sec`
#> <bch:expr> <bch:tm> <bch:tm> <dbl> <bch:byt> <dbl>
#> 1 chain 299ms 307ms 3.26 691MB 9.78
#> 2 and 123ms 142ms 7.18 231MB 5.39
summary(res, relative = TRUE)
#> # A tibble: 2 x 6
#> expression min median `itr/sec` mem_alloc `gc/sec`
#> <bch:expr> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 chain 2.43 2.16 1 2.99 1.82
#> 2 and 1 1 2.20 1 1

正如你在这里看到的 在这种情况下,anding 方法快 2.43 倍 .这意味着 链接实际上增加了一些开销 , 建议通常 anding 应该更快。 除非条件正在减小 data.table 的大小。 一步步。从理论上讲,链接方法甚至可能更慢(甚至将开销放在一边),即如果条件会增加数据的大小。但实际上我认为这是不可能的,因为 data.table 中不允许回收逻辑向量。 .我认为这回答了你的奖金问题。

作为比较,我机器上的原始功能与 bench :
res <- bench::mark(
chain = chain_filter_original(),
and = and_filter_original()
)
summary(res)
#> # A tibble: 2 x 6
#> expression min median `itr/sec` mem_alloc `gc/sec`
#> <bch:expr> <bch:tm> <bch:tm> <dbl> <bch:byt> <dbl>
#> 1 chain 29.6ms 30.2ms 28.5 79.5MB 7.60
#> 2 and 125.5ms 136.7ms 7.32 228.9MB 7.32
summary(res, relative = TRUE)
#> # A tibble: 2 x 6
#> expression min median `itr/sec` mem_alloc `gc/sec`
#> <bch:expr> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 chain 1 1 3.89 1 1.04
#> 2 and 4.25 4.52 1 2.88 1

关于r - 过滤数据表时链接 ANDing 的性能优势,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58557831/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com