R 向量化if#else或case#u when哪个不';你不急于评估它的潜在产出吗?
R 向量化if#else或case#u when哪个不';你不急于评估它的潜在产出吗?,r,if-statement,vectorization,R,If Statement,Vectorization,dplyr具有向量化条件if\u else和case\u when 然而,这两种方法都急切地评估其可能的输出(true/false对于if\u else,当发生时,case\u公式的RHS): suppress-packagestartpmessages({ 图书馆(dplyr) }) 如果是(c(T,T,T),打印(1),打印(2)) #> [1] 1 #> [1] 2 #> [1] 1 1 1 什么时候( c(T,T,T)~print(1), c(F,F,F)~print(2) ) #> [
dplyr
具有向量化条件if\u else
和case\u when
然而,这两种方法都急切地评估其可能的输出(true/false
对于if\u else
,当发生时,case\u公式的RHS):
suppress-packagestartpmessages({
图书馆(dplyr)
})
如果是(c(T,T,T),打印(1),打印(2))
#> [1] 1
#> [1] 2
#> [1] 1 1 1
什么时候(
c(T,T,T)~print(1),
c(F,F,F)~print(2)
)
#> [1] 1
#> [1] 2
#> [1] 1 1 1
由(v0.3.0)于2020年2月5日创建
在这里,我们可以清楚地看到false
案例被评估,即使它们从未被使用过。我正在寻找一种方法来避免这种情况,因为我的
有没有其他办法不这样做
我知道,一种选择实际上是base::ifelse
:
ifelse(c(T,T,T),print(1),print(2))
#> [1] 1
#> [1] 1 1 1
然而,base::ifelse
是出了名的效率低下,所以最好有一个更好的替代方案。话虽如此,我对case\u when
的替代方案特别感兴趣,当我需要使用一系列ifelse
s时,我经常使用它
我已经研究了数据。table::fifelse
,但它遇到了相同的问题:
suppress-packagestartpmessages({
库(数据表)
})
第五(c(T,T,T),打印(1),打印(2))
#> [1] 1
#> [1] 2
#> [1] 1 1 1
那么,如果安装了开发版本的数据,table
从GitHub可以使用fcase
,它类似于dplyr::case\u when
,但具有延迟评估功能:
data.table::fcase(c(TRUE, TRUE, TRUE), print(1L), c(FALSE, FALSE, FALSE), print(2L))
[1] 1
[1] 1 1 1
您可以只依赖本机R对参数传递的惰性评估,并使用all
来筛选FALSE
不存在的情况:
lazy_if_else <- function(logical_test, value_if_true, value_if_false)
{
if(all(logical_test)) return(rep(value_if_true, length.out = length(logical_test)))
if_else(logical_test, value_if_true, value_if_false)
}
如果值为true,则需要修改此值以处理非单值值,但这是一个相当不错的主意。@Wasabi您的意思是抛出错误吗?这就是“如果其他人”所做的if_else(c(T,T,T),c(1,2),c(2,3))错误:“true”必须是长度3(“条件”的长度)或1,而不是2
。这不同于只循环使用的ifelse
。@Wasabi我已经改变了它,所以它现在模仿了ifelse
的行为。基准没有太大变化。有趣的数据。table::fifelse
并不懒惰,但fcase
是索引的-特别是因为它后面是同一个人。也许data.table
开发人员会停下来更详细地解释功能,我很高兴删除我的帖子,不重复-无论如何,拥有它真的很棒,这是我之所以经常使用dplyr
的原因之一,因为没有任何真正类似的功能
microbenchmark::microbenchmark(ifelse(c(T, T, T), 0, Sys.sleep(0.1)),
if_else(c(T, T, T), 0, Sys.sleep(0.1)),
lazy_if_else(c(T, T, T), 0, Sys.sleep(0.1)))
#> Unit: microseconds
#> expr min lq mean
#> ifelse(c(T, T, T), 0, Sys.sleep(0.1)) 12.662 13.689 25.47675
#> if_else(c(T, T, T), 0, Sys.sleep(0.1)) 102723.054 109145.897 109678.33523
#> lazy_if_else(c(T, T, T), 0, Sys.sleep(0.1)) 4.791 5.476 10.80378
#> median uq max neval cld
#> 15.3995 34.904 74.255 100 a
#> 110036.0945 110176.049 116619.936 100 b
#> 6.5030 16.768 26.008 100 a