gpt4 book ai didi

r - 为什么 "logical"类型的子集比 "numeric"类型的子集慢?

转载 作者:行者123 更新时间:2023-12-03 23:51:04 25 4
gpt4 key购买 nike

假设我们有一个 vector (或 data.frame)如下:

set.seed(1)
x <- sample(10, 1e6, TRUE)

并且想要获得 x 的所有值哪里 x > 4 ,说:
a1 <- x[x > 4] # (or) 
a2 <- x[which(x > 4)]

identical(a1, a2) # TRUE

我想大多数人会更喜欢 x[x > 4] .但令人惊讶的是(至少对我而言),使用 which 进行子集化更快!
require(microbenchmark)
microbenchmark(x[x > 4], x[which(x > 4)], times = 100)

Unit: milliseconds
expr min lq median uq max neval
x[x > 4] 56.59467 57.70877 58.54111 59.94623 104.51472 100
x[which(x > 4)] 26.62217 27.64490 28.31413 29.97908 99.68973 100

我的大约快 2.1 倍。

我认为,差异的一种可能性可能是由于 which不考虑 NA但是 >也返回它们。但是逻辑运算本身应该是造成这种差异的原因,事实并非如此(显然)。即:
microbenchmark(x > 4, which(x > 4), times = 100)

Unit: milliseconds
expr min lq median uq max neval
x > 4 8.182576 10.06163 12.68847 14.64203 60.83536 100
which(x > 4) 18.579746 19.94923 21.43004 23.75860 64.20152 100

使用 which在子集之前大约慢 1.7 倍。但是 which似乎在子集化时/期间急剧 catch 。

似乎无法使用我通常选择的武器 debugonce ( thanks to @GavinSimpson ) 为 which电话 .Internal(which(x))==电话 .Primitive("==") .

因此,我的问题是为什么 [numeric类型源自 which比由 > 产生的逻辑向量更快?有什么想法吗?

最佳答案

我想我应该退出评论并添加答案。这是我根据其他人的回答和讨论建立的预感。 (我确定真正的答案存在于 subset_dflt 的 C 源代码中。)

一旦我有了一个向量 x和一个逻辑向量 x > 0 , 我可以子集 xx > 0有两种方式。我可以用 which或者我可以使用向量 x > 0直接作为索引。但是,我们必须注意这两者并不相同,因为 x[x > 0]将保留 NA同时 x[which(x > 0)]将不会。

但是,无论采用哪种方法,我都需要检查向量 x > 0 的每个元素。 .在明确的 which 中调用我将只需要检查元素的 bool 状态,而在直接子设置操作中,我将不得不检查每个元素的缺失和 bool 状态。

@flodel 带来了一个有趣的观察。自 [ , is.na , which , 和 |都是原语或内部例程,让我们假设没有特别的开销并做这个实验:

microbenchmark(which(x > 0), x[which(x > 0)], x > 0 | is.na(x), x[x > 0],
unit="us", times=1000)

Unit: microseconds
expr min lq median uq max neval
which(x > 0) 1219.274 1238.693 1261.439 1900.871 23085.57 1000
x[which(x > 0)] 1554.857 1592.543 1974.370 2339.238 23816.99 1000
x > 0 | is.na(x) 3439.191 3459.296 3770.260 4194.474 25234.70 1000
x[x > 0] 3838.455 3876.816 4267.261 4621.544 25734.53 1000

考虑中值,我们可以看到,假设 x > 0 | is.na(x)是我所说的发生在逻辑子集的粗略模型,然后在“子集”中实际花费的时间是 ~ 500 us。 'subset' 所用的时间约为 700 us。这两个数字是可比的,并表明在一种或另一种方法中成本高昂的并不是“子集”本身。相反,正在执行的操作是计算 which 中更便宜的所需子集。方法。

关于r - 为什么 "logical"类型的子集比 "numeric"类型的子集慢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17510778/

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