web-dev-qa-db-fra.com

dplyr if_else () vs base R ifelse ()

Je suis assez compétent dans le Tidyverse, mais j'ai toujours utilisé ifelse() au lieu de dplyr if_else(). Je veux changer ce comportement et par défaut pour toujours utiliser dplyr::if_else() et déprécier ifelse() de mon code.

Y a-t-il une raison de ne pas le faire? Est-ce que cela m'aurait probablement des ennuis? Je vais vous épargner les détails, mais récemment, ne pas utiliser if_else() m'a bousillé, quand j'ai créé sans le savoir une colonne de matrices de caractères dans mon analyse de données. Si je passe à toujours utiliser if_else() j'espère éviter ce problème à l'avenir.

15
stackinator

if_else est plus strict. Il vérifie que les deux alternatives sont du même type et génère une erreur, tandis que ifelse promouvra les types si nécessaire. Cela peut être un avantage dans certaines circonstances, mais peut sinon casser les scripts si vous ne recherchez pas d'erreurs ou ne forcez pas explicitement la conversion de type. Par exemple:

ifelse(c(TRUE,TRUE,FALSE),"a",3)
[1] "a" "a" "3"
if_else(c(TRUE,TRUE,FALSE),"a",3)
Error: `false` must be type character, not double
17
James

Une autre raison de choisir if_else sur ifelse est que ifelse transforme Date en numeric objets

Dates <- as.Date(c('2018-10-01', '2018-10-02', '2018-10-03'))
new_Dates <- ifelse(Dates == '2018-10-02', Dates + 1, Dates)
str(new_Dates)

#>  num [1:3] 17805 17807 17807

if_else est également plus rapide que ifelse .

Notez que lorsque vous testez plusieurs conditions, le code serait plus lisible et moins sujet aux erreurs si nous utilisons case_when.

library(dplyr)

case_when(
  Dates == '2018-10-01' ~ Dates - 1,
  Dates == '2018-10-02' ~ Dates + 1,
  Dates == '2018-10-03' ~ Dates + 2,
  TRUE ~ Dates
)

#> [1] "2018-09-30" "2018-10-03" "2018-10-05"

Créé le 2018-06-01 par le package reprex (v0.2.0).

10
Tung

J'ajouterais également que if_else() peut attribuer une valeur en cas de NA, ce qui est un moyen pratique d'ajouter une condition supplémentaire.

df <- data_frame(val = c(80, 90, NA, 110))
df %>% mutate(category = if_else(val < 100, 1, 2, missing = 9))

#     val category
#   <dbl>    <dbl>
# 1    80        1
# 2    90        1
# 3    NA        9
# 4   110        2
5
Joe