O ifelse realmente calcula ambos os vetores toda vez? É lento?

O ifelse realmente calcula os vetores yes e no – como na totalidade de cada vetor? Ou apenas calcula alguns valores de cada vetor?

Além disso, o ifelse é realmente tão lento?

    Sim. (Com exceção)

    ifelse calcula seu valor yes e seu valor ifelse . Exceto no caso em que a condição de test é ou TRUE ou FALSE .

    Podemos ver isso gerando números randoms e observando quantos números são realmente gerados. (revertendo a seed ).

     # TEST CONDITION, ALL TRUE set.seed(1) dump < - ifelse(rep(TRUE, 200), rnorm(200), rnorm(200)) next.random.number.after.all.true <- rnorm(1) # TEST CONDITION, ALL FALSE set.seed(1) dump <- ifelse(rep(FALSE, 200), rnorm(200), rnorm(200)) next.random.number.after.all.false <- rnorm(1) # TEST CONDITION, MIXED set.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 MATCH set.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 ) 

    Dá a seguinte saída:

     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 

    Nós também podemos ver isso no próprio código-fonte:

     . . 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] . . 

    Observe que yes e no são computados apenas se houver algum valor de test de NA que seja TRUE ou FALSE (respectivamente).
    Em que ponto - e esta é a parte importante quando se trata de eficiência - a totalidade de cada vetor é computada.


    Ok, mas é mais lento?

    Vamos ver se podemos testá-lo:

     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 

    Estas duas declarações geram os mesmos resultados

     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 

    mas um é duas vezes mais rápido que o outro

     microbenchmark(eval(yesifelse), eval(noiflese), times=50L) N = 1,000 Unit: 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 50 N = 10,000 Unit: 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