vectores vacio seleccionar operaciones listas ifelse eliminar elementos crear contar concatenar con columnas r performance if-statement vectorization

vacio - ¿Ifelse realmente calcula ambos vectores cada vez? ¿Es lento?



operaciones con vectores en r (1)

Sí. (Con excepción)

ifelse calcula tanto su valor yes como su valor no . Excepto en el caso en que la condición de test sea TRUE o FALSE .

Podemos ver esto generando números aleatorios y observando cuántos números realmente se generan. (invirtiendo la 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 )

Da el siguiente resultado:

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

También podemos verlo en el código fuente en sí:

. . 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 y no se computan solo si hay algún valor de test no NA que sea TRUE o FALSE (respectivamente).
En ese punto, y esta es la parte importante en lo que respecta a la eficiencia, se computa la totalidad de cada vector .

Ok, pero ¿es más lento?

Veamos si podemos probarlo:

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 dos declaraciones generan los mismos 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

pero uno es dos veces más rápido que el otro

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

¿Realmente ifelse calcula los vectores yes y no , como en, la totalidad de cada vector? ¿O solo calcula algunos valores de cada vector?

Además, ¿es realmente tan lento?