datazang
datazang

Reputation: 1179

How to change the numerical values in multiple columns?

I have a data set something like this:

df <- tribble(
        ~X,     ~Y,    ~Z,
        "a",     0,     2,  
        "b",     5,     0, 
        "c",     0,     0, 
        "d",     3,     1, 
        "e",     0,     2, 
)

Now, I want to revalue the values in the column of Y and Z if they are zero. So, I basically use the function of case_when. But this returned the values NA if they are non-zero.

df_desired <- df %>% 
  mutate(Y = case_when(Y == 0 ~ 0.0001),
         Z = case_when(Z == 0 ~ 0.0001))

I was wondering what I am missing the code. Thanks in advance.

Upvotes: 1

Views: 68

Answers (1)

akrun
akrun

Reputation: 887971

By default, the case_when default values i.e TRUE returns NA unless specified. According to ?case_when

This function allows you to vectorise multiple if_else() statements. It is an R equivalent of the SQL CASE WHEN statement. If no cases match, NA is returned.

Here, the no cases match is returning NA unless the default condition with TRUE is provided

library(dplyr)
df %>%  
   mutate(Y = case_when(Y == 0 ~ 0.0001, TRUE ~ Y),  
          Z = case_when(Z == 0 ~ 0.0001, TRUE ~ Z))

which can be made more compact with mutate_at

df %>%
   mutate_at(vars(Y, Z), ~ case_when(. == 0 ~ 0.0001, TRUE ~ .))

Also, in this case, replace may be more compact

df %>%
   mutate_at(vars(Y, Z), ~ replace(., .== 0, 0.0001))

Or may be arithmetic

df %>%
    mutate_at(vars(Y, Z), ~  . + (. == 0) * 0.0001)

@Junitar's suggested to check the type if we want to apply on numeric columns

df %>%
    mutate_if(is.numeric,  ~ case_when(. == 0 ~ 0.0001, TRUE ~ .))

Upvotes: 1

Related Questions