为了账号安全,请及时绑定邮箱和手机立即绑定

是否真的每次都计算两个向量?很慢吗?

/ 猿问

是否真的每次都计算两个向量?很慢吗?

呼唤远方 2019-06-17 17:38:20

是否真的每次都计算两个向量?很慢吗?

是吗?ifelse实际计算两个yesno向量-每个向量的整体?或者它只是从每个向量中计算一些值?

还有,是ifelse真的那么慢?


查看完整描述

3 回答

?
郎朗坤

是。(例外)

ifelse计算其yes价值及其no价值。但在下列情况下,则不在此限test条件不是全部TRUE或者全部FALSE.

我们可以通过产生随机数和观察实际生成多少个数字来看到这一点。(通过恢复seed).

# TEST CONDITION, ALL TRUEset.seed(1)dump  <- ifelse(rep(TRUE, 200), rnorm(200), rnorm(200))next.random.number.after.all.true <- rnorm(1)
# TEST CONDITION, ALL FALSEset.seed(1)dump  <- ifelse(rep(FALSE, 200), rnorm(200), rnorm(200))next.random.number.after.all.false <- rnorm(1)
# TEST CONDITION, MIXEDset.seed(1)dump   <- ifelse(c(FALSE, rep(TRUE, 199)), rnorm(200), rnorm(200))next.random.number.after.
some.TRUE.some.FALSE <- rnorm(1)# RESET THE SEED, GENERATE SEVERAL RANDOM NUMBERS TO SEARCH FOR A MATCHset.seed(1)
r.1000 <- rnorm(1000)cat("Quantity of random numbers generated during the `ifelse` statement when:", 
    "\n\tAll True  ", which(r.1000 == next.random.number.after.all.true) - 1,
    "\n\tAll False ", which(r.1000 == next.random.number.after.all.false) - 1,
    "\n\tMixed T/F ", which(r.1000 == next.random.number.after.some.TRUE.some.FALSE) - 1 
  )

给出以下输出:

Quantity of random numbers generated during the `ifelse` statement when: 
  All True   200 
  All False  200 
  Mixed T/F  400   <~~ Notice TWICE AS MANY numbers were
                       generated when `test` had both
                       T & F values present

我们还可以在源代码本身中看到它:

.
.if (any(test[!nas]))    
    ans[test & !nas] <- rep(yes, length.out = length(ans))[test &   # <~~~~ This line and the one below
        !nas]if (any(!test[!nas])) 
    ans[!test & !nas] <- rep(no, length.out = length(ans))[!test &  # <~~~~ ... are the cluprits
        !nas].
.

注意yesno只有当有一些非-NA价值test那是TRUEFALSE(分别)。
在这一点上-这是效率的重要部分-每个向量的整体都是计算出来的。


好的,但是速度慢吗?

让我们看看是否可以测试它:

library(microbenchmark)# Create some sample data
  N <- 1e4
  set.seed(1)
  X <- sample(c(seq(100), rep(NA, 100)), N, TRUE)
  Y <- ifelse(is.na(X), rnorm(X), NA)  # Y has reverse NA/not-NA setup than X

这两条语句产生相同的结果。

yesifelse <- quote(sort(ifelse(is.na(X), Y+17, X-17 ) ))noiflese  <- quote(sort(c(Y[is.na(X)]+17, X[is.na(Y)]-17)))identical(eval(yesifelse),
 eval(noiflese))# [1] TRUE

但其中一个速度是另一个的两倍

microbenchmark(eval(yesifelse), eval(noiflese), times=50L)N = 1,000Unit: milliseconds
            expr      min       lq   median       uq      max neval
 eval(yesifelse) 2.286621 2.348590 2.411776 2.537604 10.05973    50
  eval(noiflese) 1.088669 1.093864 1.122075 1.149558 61.23110    50N = 10,000Unit: milliseconds
            expr      min       lq   median       uq      max neval
 eval(yesifelse) 30.32039 36.19569 38.50461 40.84996 98.77294    50
  eval(noiflese) 12.70274 13.58295 14.38579 20.03587 21.68665    50


查看完整回答
反对 回复 2019-06-17
?
芜湖不芜

顺便说一句,我不是在抨击ifelse..事实上,我一直在使用它,除非我需要效率

查看完整回答
反对 回复 2019-06-17
?
白板的微信

我现在更明白这一点。如果可以的话我会给一个+2的。我明白你说的了。更好的是ifelse用这样的方法rep(yes, length.out = length(ans) - sum(! test & ok ) )而不是默认rep(yes, length.out = length(ans))[test & !nas]停止不相关的评估yes

查看完整回答
反对 回复 2019-06-17

添加回答

回复

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信