Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/codeigniter/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
R 向量化if#else或case#u when哪个不';你不急于评估它的潜在产出吗?_R_If Statement_Vectorization - Fatal编程技术网

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