idiom for replacing `NA` with 0 in *only* numerical fields in a data frame

I've been using the following idiom for replacing NA with 0 in all numeric fields in a data frame:

df %>%
   mutate_if(is.numeric, funs(replace_na(., 0)))

dplyr is now telling me:

## Warning: funs() is soft deprecated as of dplyr 0.8.0
## please use list() instead
## 
## # Before:
## funs(name = f(.)
## 
## # After: 
## list(name = ~f(.))
## This warning is displayed once per session.

But in this use case I can't just drop in list and it work. Is there a more modern idiom I should be using?

Obligatory reprex:


library(tidyverse)
df <- data.frame(char = letters[1:4], 
                 a = c(1:3,NA), 
                 b = c(NA,4:6))

df %>% 
  mutate_if(is.numeric, funs(replace_na(., 0)))
#> Warning: funs() is soft deprecated as of dplyr 0.8.0
#> please use list() instead
#> 
#> # Before:
#> funs(name = f(.)
#> 
#> # After: 
#> list(name = ~f(.))
#> This warning is displayed once per session.
#>   char a b
#> 1    a 1 0
#> 2    b 2 4
#> 3    c 3 5
#> 4    d 0 6

df %>% 
  mutate_if(is.numeric, list(replace_na(., 0)))
#> Error in replace_na.data.frame(., 0): is_list(replace) is not TRUE

Created on 2019-04-10 by the reprex package (v0.2.1)

You just need to add ~ before the function inside list().

df %>% 
  mutate_if(is.numeric, list(~replace_na(., 0)))

  char a b
1    a 1 0
2    b 2 4
3    c 3 5
4    d 0 6

Hope this helps.

2 Likes

Also, since you are just using one function and you are mutating in-place, you can just use ~ alone.

df %>% 
    mutate_if(is.numeric, ~replace_na(., 0))
#>   char a b
#> 1    a 1 0
#> 2    b 2 4
#> 3    c 3 5
#> 4    d 0 6
6 Likes

You can also supply the extra arguments directly to mutate_if:

df %>% mutate_if(is.numeric, replace_na, replace = 0)
2 Likes

I know I should drink the Kool Aid and get on board with the ~ syntax, but I must admit I like this syntax better.

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

If you have a query related to it or one of the replies, start a new topic and refer back with a link.