Liam O'Halloran
Liam O'Halloran

Reputation: 15

using dplyr case_when to alter NA values based on value from another column

structure(list(a = c(NA, 3, 4, NA, 3, "Council" , "Council", 1), b = c("Council A", 3, 4, 
"Council B", 6, 7, 2, 6), c = c(6, 3, 6, 5, 3, 6, 5, 3), d = c(6, 2, 4, 
5, 3, 7, 2, 6), e = c(1, 2, 4, 5, 6, 7, 6, 3), f = c(2, 3, 4, 
2, 2, 7, 5, 2)), .Names = c("a", "b", "c", "d", "e", "f"), row.names = c(NA, 
8L), class = "data.frame")

I am trying to convert objects in a using dplyr mutuate and case_when based on text in b . I want to convert values in a to Council if b contains Council in the string.

The code i've used is DF %>% select(a, b) %>% mutate(a =case_when(grepl("Council", b) ~"Council"))

However all values become NA in a if they do not contain the string Council. I've reviewed other posts and attempted various methods including ifelse. I want to maintain the same dataframe just make any NA values in a be converted to Council but only in the cases where it is NA values.

Upvotes: 1

Views: 2128

Answers (2)

Swapnil
Swapnil

Reputation: 164

You can also use str_detect from the package stringr to achieve your objective.

library(dplyr)
library(stringr)

df <- structure(list(a = c(NA, 3, 4, NA, 3, "Council" , "Council", 1), b = c("Council A", 3, 4, 
                                                                   "Council B", 6, 7, 2, 6), c = c(6, 3, 6, 5, 3, 6, 5, 3), d = c(6, 2, 4, 
                                                                                                                                  5, 3, 7, 2, 6), e = c(1, 2, 4, 5, 6, 7, 6, 3), f = c(2, 3, 4, 
                                                                                                                                                                                       2, 2, 7, 5, 2)), .Names = c("a", "b", "c", "d", "e", "f"), row.names = c(NA, 
                                                                                                                                                                                                                                                                8L), class = "data.frame")

df %>% 
  mutate(a=ifelse(str_detect(b,fixed("council",ignore_case = T)) & is.na(a),"Council",a))

Upvotes: 0

Ronak Shah
Ronak Shah

Reputation: 388862

From ?case_when

If no cases match, NA is returned.

So for the cases when there is no "Council" word in b it returns NA.

You need to define the TRUE argument in case_when and assign it to a to keep the values unchanged when the condition is not met.

library(dplyr)

df %>%  
 mutate(a = case_when(grepl("Council", b) ~"Council",
                        TRUE ~ a))


#        a         b c d e f
#1 Council Council A 6 6 1 2
#2       3         3 3 2 2 3
#3       4         4 6 4 4 4
#4 Council Council B 5 5 5 2
#5       3         6 3 3 6 2
#6 Council         7 6 7 7 7
#7 Council         2 5 2 6 5
#8       1         6 3 6 3 2

In this case you could also achieve your result using base R

df$a[grepl("Council", df$b)] <- "Council"

Upvotes: 4

Related Questions