Mike Mike - 1 month ago 19
R Question

Conditionally Recoding Mutiple Columns into One New Column with Dplyr Mutate and If_Else

Using the simple dataframe below, I wanto create a new column that contains a 1 for instances where City = "Toronto" and PostInjury = "0-1", a 2 for instances when City= "Montreal" and PostInjury ="6-10", and a 3 for everything else.

I want to use mutate and if_else, but not sure how to use this combination to conditionally recode multiple column combinations into one new column without intermediate steps? I can use two if_else statements to create two new columns, then combine them with Tidyr's unite and then recode, but that seems very tedious.

Am I missing something elegant? I have a feeling I am. Is there a way to use if_else in this way with dplyr, or perhaps with case_when?

City<-c("Toronto", "Toronto", "Montreal","Ottawa","Montreal",
"Hamilton","Peterborough","Toronto","Hamilton","Montreal")

Client<-c("Cl1","Cl2","Cl3","Cl4","Cl5","Cl6","Cl7","Cl8","Cl9","Cl10")

PostInjury<-c("0-1","6-10","0-1","2-5","6-10","0-1","11-15","0-1","0-1","6-10")

DF<- data.frame(City,Client,PostInjury)

Answer

You can use nested ifelse. With dplyr:

DF <- DF %>% 
  mutate(new_column = if_else(City == "Toronto" & PostInjury == "0-1", 1,
    if_else(City == "Montreal" & PostInjury == "6-10", 2, 3)))

Using case_when:

DF <- DF %>% mutate(new_column = 
  case_when(
      City == "Toronto" & PostInjury == "0-1" ~ 1,
      City == "Montreal" & PostInjury == "6-10" ~ 2, 
      TRUE ~ 3
  )
)

Or with base functions:

DF$new_column <- ifelse(DF$City == "Toronto" & DF$PostInjury == "0-1", 1,
  ifelse(DF$City == "Montreal" & DF$PostInjury == "6-10", 2, 3))

Or

DF$new_column <- sapply(as.character(interaction(DF$City, DF$PostInjury)),
  switch, 
  "Toronto.0-1" = 1,
  "Montreal.6-10" = 2,
  3)
Comments