Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using `mutate_at` and `na_if` together to replace zeros with NA for only some columns

Tags:

r

dplyr

tidyverse

My data takes this format:

library(tidyverse)
df <- mtcars
df <- df %>% mutate(vs_doubled = vs * 2) %>% select(mpg, cyl, vs, am, vs_doubled)

head(df)


#>    mpg cyl vs am vs_doubled
#> 1 21.0   6  0  1          0
#> 2 21.0   6  0  1          0
#> 3 22.8   4  1  1          2
#> 4 21.4   6  1  0          2
#> 5 18.7   8  0  0          0
#> 6 18.1   6  1  0          2

I'm trying to use mutate_at and na_if to set 0 values as NA--but only for specific columns ("vs" and "am"). I would like to leave the column "vs_doubled" with zeros in it.

I haven't quite got it right, because the following line doesn't work:

df <- df %>% mutate_at(.vars = c("vs", "am"), .funs = na_if(y = 0))
like image 755
Jeremy K. Avatar asked Jul 08 '19 05:07

Jeremy K.


Video Answer


1 Answers

Update

From dplyr 1.0.0 we can use across :

library(dplyr)
df %>% mutate(across(c(vs,am), na_if, 0)) %>% head

#   mpg cyl vs am vs_doubled
#1 21.0   6 NA  1          0
#2 21.0   6 NA  1          0
#3 22.8   4  1  1          2
#4 21.4   6  1 NA          2
#5 18.7   8 NA NA          0
#6 18.1   6  1 NA          2

Original answer

In the previous versions of dplyr we can use mutate_at :

df %>%  mutate_at(vars(vs,am), ~na_if(.,0)) %>% head

Or another way would be

df %>% mutate_at(vars(vs,am), na_if, 0)

~ is purrr-styled formula syntax whereas . represents value of the column. It's an alternative to anonymous function calls with which you would have written the above function as

df %>%  mutate_at(vars(vs,am), function(x) na_if(x, 0)) 

Also the alternative way shown does not require ~ and we can directly pass the function with additional arguments (which is 0 here for y).


And of course there are other ways to do this without using na_if

df %>% mutate_at(vars(vs, am), ~replace(., . == 0, NA)) 

Or the same with base R

cols <- c("vs", "am")
df[cols] <- lapply(df[cols], function(x) replace(x, x == 0, NA))
like image 146
Ronak Shah Avatar answered Sep 20 '22 21:09

Ronak Shah