How to recode a range of values in a variable and coerce it to a factor?

Using cut with labels:

df$education_recoded <- cut(df$education, breaks = c(0,3,5), 
                            labels = c("Up to secondary school", 
                                       "University studies or higher"))
# compare the values
table(df$education_recoded, df$education)
#                               1  2  3  4  5
# Up to secondary school       21 24 24  0  0
# University studies or higher  0  0  0 15 16

Or using pipes:

library(dplyr)  

df %>% 
  mutate(education_recoded = cut(education, breaks = c(0,3,5), 
                                 labels = c("Up to secondary school", 
                                            "University studies or higher")))