`if`比ifelse更快? [英] Is `if` faster than ifelse?
问题描述
当我最近重新阅读Hadley的Advanced R时,我注意到他在第6章中说过`if`
可以用作
之类的函数
`if`(i == 1,print(yes),print(no))
(如果你有实体书,它在第80页上)
When I was re-reading Hadley's Advanced R recently, I noticed that he said in Chapter 6 that `if`
can be used as a function like
`if`(i == 1, print("yes"), print("no"))
(If you have the physical book in hand, it's on Page 80)
我们知道 ifelse
很慢( ifelse是否真的计算了它的两个向量每一次?慢吗?)因为它评估所有论点。将`if`
替换为,如果
似乎只评估 TRUE
参数(这只是我的假设)?
We know that ifelse
is slow (Does ifelse really calculate both of its vectors every time? Is it slow?) as it evaluates all arguments. Will `if`
be a good alternative to that as if
seems to only evaluate TRUE
arguments (this is just my assumption)?
更新:根据@Benjamin和@Roman的答案以及@Gregor和其他许多人的评论, ifelse
似乎是矢量化计算的更好解决方案。我正在接受@ Benjamin的回答,因为它提供了更全面的比较和社区健康。但是,两个答案(和评论)都值得一读。
Update: Based on the answers from @Benjamin and @Roman and the comments from @Gregor and many others, ifelse
seems to be a better solution for vectorized calculations. I'm taking @Benjamin's answer here as it provides a more comprehensive comparison and for the community wellness. However, both answers(and the comments) are worth reading.
推荐答案
这是罗马答案的扩展评论,但我需要代码实用程序来解释:
This is more of an extended comment building on Roman's answer, but I need the code utilities to expound:
罗马是正确的如果
比 ifelse
更快,但我是在如果
的速度提升不是特别有趣的印象下,因为它不是可以通过矢量化轻松利用的东西。也就是说,当 cond $ c时,
如果
仅优于 ifelse
$ c> / test
参数长度为1。
Roman is correct that if
is faster than ifelse
, but I am under the impression that the speed boost of if
isn't particularly interesting since it isn't something that can easily be harnessed through vectorization. That is to say, if
is only advantageous over ifelse
when the cond
/test
argument is of length 1.
考虑以下函数,这是一个无可否认的弱尝试vectorizing if
,而不会产生评估 yes
和 no $ c的副作用$ c>条件为
ifelse
。
Consider the following function which is an admittedly weak attempt at vectorizing if
without having the side effect of evaluating both the yes
and no
conditions as ifelse
does.
ifelse2 <- function(test, yes, no){
result <- rep(NA, length(test))
for (i in seq_along(test)){
result[i] <- `if`(test[i], yes[i], no[i])
}
result
}
ifelse2a <- function(test, yes, no){
sapply(seq_along(test),
function(i) `if`(test[i], yes[i], no[i]))
}
ifelse3 <- function(test, yes, no){
result <- rep(NA, length(test))
logic <- test
result[logic] <- yes[logic]
result[!logic] <- no[!logic]
result
}
set.seed(pi)
x <- rnorm(1000)
library(microbenchmark)
microbenchmark(
standard = ifelse(x < 0, x^2, x),
modified = ifelse2(x < 0, x^2, x),
modified_apply = ifelse2a(x < 0, x^2, x),
third = ifelse3(x < 0, x^2, x),
fourth = c(x, x^2)[1L + ( x < 0 )],
fourth_modified = c(x, x^2)[seq_along(x) + length(x) * (x < 0)]
)
Unit: microseconds
expr min lq mean median uq max neval cld
standard 52.198 56.011 97.54633 58.357 68.7675 1707.291 100 ab
modified 91.787 93.254 131.34023 94.133 98.3850 3601.967 100 b
modified_apply 645.146 653.797 718.20309 661.568 676.0840 3703.138 100 c
third 20.528 22.873 76.29753 25.513 27.4190 3294.350 100 ab
fourth 15.249 16.129 19.10237 16.715 20.9675 43.695 100 a
fourth_modified 19.061 19.941 22.66834 20.528 22.4335 40.468 100 a
一些编辑:感谢Frank和Richard Scriven注意到我的短信omings。
SOME EDITS: Thanks to Frank and Richard Scriven for noticing my shortcomings.
正如您所看到的,如果是分解向量以便传递给的过程是一个耗时的过程,最终比运行
ifelse
慢(这可能是为什么没有人费心去实现我的解决方案)。
As you can see, the process of breaking up the vector to be suitable to pass to if
is a time consuming process and ends up being slower than just running ifelse
(which is probably why no one has bothered to implement my solution).
如果您真的非常渴望提高速度,可以使用上面的 ifelse3
方法。或者更好的是,弗兰克不那么明显*但很棒的解决方案。
If you're really desperate for an increase in speed, you can use the ifelse3
approach above. Or better yet, Frank's less obvious* but brilliant solution.
- '不太明显'我的意思是,我花了两秒钟才意识到什么他做到了。根据下面nicola的评论,请注意,这只适用于
是
和没有
长度为1,否则你将会想坚持ifelse3
- by 'less obvious' I mean, it took me two seconds to realize what he did. And per nicola's comment below, please note that this works only when
yes
andno
have length 1, otherwise you'll want to stick withifelse3
这篇关于`if`比ifelse更快?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!