if-else not working properly and returing desired/expected values

I am trying to create a new column and have values derived from another column in a dataframe using if-else or case-when but i am only getting the first condition satisfied and not going to else part thereby populating all the records with the first value.

New column:Quarter
Column from which values are to be derived:Month

unique(promax_2020_data$month)
[1] "Jan" "Feb" "Mar" "Apr" "May" "Jun" "Jul" "Aug" "Sep"

If-else code:-

promax_2020_data$Quarter<-if (promax_2020_data$month %in% c("Jan","Feb","Mar")){
"Q1"
} else if (promax_2020_data$month %in% c("Apr","May","Jun")){
"Q2"
} else {
"Q3"
}

Warning message:
In if (promax_2020_data$month %in% c("Jan", "Feb", "Mar")) { :
the condition has length > 1 and only the first element will be used

promax_2020_data$Quarter <- {
case_when(
promax_2020_data$month=="Jan" || promax_2020_data$month=="Feb" || promax_2020_data$month=="Mar" ~ "Q1",
promax_2020_data$month=="Apr" || promax_2020_data$month=="May" || promax_2020_data$month=="Jun" ~ "Q2",
promax_2020_data$month=="Jul" || promax_2020_data$month=="Aug" || promax_2020_data$month=="Sep" ~ "Q3",
TRUE ~ "Q4"
)
}
Although using case when doesn't give any error or warning like if-else but this also populates all the records with Q1 only.

Rather than using the normal if() function, you would want to use the vectorized ifelse. Since there are multiple conditions, it is better to use case_when.

library(dplyr)
promax_2020_data <- mutate(promax_2020_data, Quarter = case_when(
month %in% c("Jan", "Feb", "Mar") ~ "Q1",
month %in% c("Apr", "May", "Jun") ~ "Q2",
month %in% c("Jul", "Aug", "Sep") ~ "Q3",
TRUE ~ "Q4"
))

I hope I wrote that without typos.

Agreed: case_when is the way to go here. @ritm in case you need a full explanation of the syntax and reasoning behind the case_when function, I'll engage in a little shameless self-promotion: I wrote a blog post about this function, which you can read here.

Might I suggest a different approach that I think is easier to type and understand and less error prone


set.seed(1)
d <- data.frame(m = month.abb)
d
#>      m
#> 1  Jan
#> 2  Feb
#> 3  Mar
#> 4  Apr
#> 5  May
#> 6  Jun
#> 7  Jul
#> 8  Aug
#> 9  Sep
#> 10 Oct
#> 11 Nov
#> 12 Dec

d$q <- ceiling(match(d$m, month.abb) / 3)
d
#>      m q
#> 1  Jan 1
#> 2  Feb 1
#> 3  Mar 1
#> 4  Apr 2
#> 5  May 2
#> 6  Jun 2
#> 7  Jul 3
#> 8  Aug 3
#> 9  Sep 3
#> 10 Oct 4
#> 11 Nov 4
#> 12 Dec 4

Created on 2020-10-15 by the reprex package (v0.3.0)