Using if_else and getting warning because of type error

When using the function dplyr::if_else, it applies the "else" function on everything which causes a type issue. Is there any way to avoid this? I get the correct results but I really like seeing a clean log in code with no warnings.

library(tibble)
library(magrittr)
library(dplyr)
#> 
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#> 
#>     filter, lag
#> The following objects are masked from 'package:base':
#> 
#>     intersect, setdiff, setequal, union

# problem that as.numeric is run on case where it isn't a number
tibble(YearOrig=c(as.character(2015:2019), "2017:2019")) %>%
  mutate(Year=if_else(YearOrig=="2017:2019", 9999, as.numeric(YearOrig)))
#> Warning in replace_with(out, !condition, false, fmt_args(~false), glue("length
#> of {fmt_args(~condition)}")): NAs introduced by coercion
#> # A tibble: 6 x 2
#>   YearOrig   Year
#>   <chr>     <dbl>
#> 1 2015       2015
#> 2 2016       2016
#> 3 2017       2017
#> 4 2018       2018
#> 5 2019       2019
#> 6 2017:2019  9999

# this gives no warning because that case doesn't exist
tibble(YearOrig=c(as.character(2015:2019))) %>%
  mutate(Year=if_else(YearOrig=="2017:2019", 9999, as.numeric(YearOrig)))
#> # A tibble: 5 x 2
#>   YearOrig  Year
#>   <chr>    <dbl>
#> 1 2015      2015
#> 2 2016      2016
#> 3 2017      2017
#> 4 2018      2018
#> 5 2019      2019

Created on 2020-08-23 by the reprex package (v0.3.0)

The warning has nothing to do with if_else(), but is purely due to as.numeric("2017:2019"). It doesn't give a warning in the second case because the argument is not evaluated.

I'm afraid if_else() will always evaluates its arguments at once when needed, since everything is vectorized. If you wanted to only evaluate the rows where the false condition is used, you would need to rewrite a non-vectorized version (with for and if).

In your case, I think the best way is to explicitly treat the non-numeric cases as strings before calling as.numeric():

tibble(YearOrig=c(as.character(2015:2019), "2017:2019")) %>%
  mutate(YearOrig2 = str_replace(YearOrig, "2017:2019", replacement = "9999"),
         Year=if_else(YearOrig2=="9999", 9999, as.numeric(YearOrig2)))

(of course in that example the if_else becomes unnecessary)

suppressPackageStartupMessages(library(dplyr))
tibble(YearOrig=c(seq(from = 2015, to = 2019,1))) %>%
  mutate(YearOrig = ifelse(YearOrig > 2016,9999,YearOrig))
#> # A tibble: 5 x 1
#>   YearOrig
#>      <dbl>
#> 1     2015
#> 2     2016
#> 3     9999
#> 4     9999
#> 5     9999

Created on 2020-08-23 by the reprex package (v0.3.0)

Preferable, however, avoid the magic number, use NA

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.