Est-ce que ifelse
calcule vraiment à la fois les vecteurs oui
et non
- c'est-à-dire, l'intégralité de chaque vecteur ? Ou calcule-t-il simplement certaines valeurs de chaque vecteur ?
Aussi, est-ce que ifelse
est vraiment si lent ?
Est-ce que ifelse
calcule vraiment à la fois les vecteurs oui
et non
- c'est-à-dire, l'intégralité de chaque vecteur ? Ou calcule-t-il simplement certaines valeurs de chaque vecteur ?
Aussi, est-ce que ifelse
est vraiment si lent ?
ifelse
calcule à la fois sa valeur oui
et sa valeur non
. Sauf dans le cas où la condition test
est soit entièrement TRUE
soit entièrement FALSE
.
Nous pouvons voir cela en générant des nombres aléatoires et en observant combien de nombres sont réellement générés (en inversant la seed
).
# CONDITION TEST, TOUT VRAI
set.seed(1)
dump <- ifelse(rep(TRUE, 200), rnorm(200), rnorm(200))
nombre.aléatoire.suivant.après.tout.vrai <- rnorm(1)
# CONDITION TEST, TOUT FAUX
set.seed(1)
dump <- ifelse(rep(FALSE, 200), rnorm(200), rnorm(200))
nombre.aléatoire.suivant.après.tout.faux <- rnorm(1)
# CONDITION TEST, MÉLANGÉ
set.seed(1)
dump <- ifelse(c(FALSE, rep(TRUE, 199)), rnorm(200), rnorm(200))
nombre.aléatoire.suivant.après.un.peu.VRAI.un.peu.FAUX <- rnorm(1)
# RÉINITIALISER LA SEED, GÉNÉRER PLUSIEURS NOMBRES ALÉATOIRES POUR RECHERCHER UNE CORRESPONDANCE
set.seed(1)
r.1000 <- rnorm(1000)
cat("Quantité de nombres aléatoires générés pendant l'instruction `ifelse` lorsque :",
"\n\tTout Vrai ", which(r.1000 == nombre.aléatoire.suivant.après.tout.vrai) - 1,
"\n\tTout Faux ", which(r.1000 == nombre.aléatoire.suivant.après.tout.faux) - 1,
"\n\tMélangé V/F", which(r.1000 == nombre.aléatoire.suivant.après.un.peu.VRAI.un.peu.FAUX) - 1
)
Donne la sortie suivante :
Quantité de nombres aléatoires générés pendant l'instruction `ifelse` lorsque :
Tout Vrai 200
Tout Faux 200
Mélangé V/F 400 <~~ Remarquez DEUX FOIS PLUS de nombres ont été générés lorsque la condition contenait à la fois des valeurs V et F
.
.
if (any(test[!nas]))
ans[test & !nas] <- rep(yes, length.out = length(ans))[test & # <~~~~ Cette ligne et celle ci-dessous
!nas]
if (any(!test[!nas]))
ans[!test & !nas] <- rep(no, length.out = length(ans))[!test & # <~~~~ ... sont les coupables
!nas]
.
.
Remarquez que les valeurs yes
et no
sont calculées uniquement s'il existe une valeur non-NA
de test
qui est TRUE
ou FALSE
(respectivement).
À ce stade - et c'est l'aspect important en termes d'efficacité - la totalité de chaque vecteur est calculée.
Voyons si nous pouvons le tester :
library(microbenchmark)
# Créez quelques données d'exemple
N <- 1e4
set.seed(1)
X <- sample(c(seq(100), rep(NA, 100)), N, TRUE)
Y <- ifelse(is.na(X), rnorm(X), NA) # Y a une configuration NA/non-NA inversée par rapport à X
ouiifelse <- quote(sort(ifelse(is.na(X), Y+17, X-17 ) ))
noniflese <- quote(sort(c(Y[is.na(X)]+17, X[is.na(Y)]-17)))
identical(eval(ouiifelse), eval(noniflese))
# [1] TRUE
microbenchmark(eval(ouiifelse), eval(noniflese), times=50L)
N = 1,000
Unité: millisecondes
expr min lq médiane uq max neval
eval(ouiifelse) 2.286621 2.348590 2.411776 2.537604 10.05973 50
eval(noniflese) 1.088669 1.093864 1.122075 1.149558 61.23110 50
N = 10,000
Unité: millisecondes
expr min lq médiane uq max neval
eval(ouiifelse) 30.32039 36.19569 38.50461 40.84996 98.77294 50
eval(noniflese) 12.70274 13.58295 14.38579 20.03587 21.68665 50
Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.