I would use the cut function to do what you are doing. Afterwards, you could then use the fct_collapse to modify your cut points. You could do something like the following:
library(dplyr)
library(forcats)
library(ggplot2)
iris %>%
filter(Species == "setosa") %>%
mutate(sub_species = cut(Sepal.Length, breaks = c(-Inf, 4.7, 5, 5.2, Inf))) %>%
mutate(sub_species = fct_collapse(sub_species,
combined = c("(-Inf,4.7]", "(5.2, Inf]"))) %>%
ggplot(aes(sub_species, Petal.Length))+
geom_boxplot()
And that will give you want you want.
Alternatively, you could replace the cut function and use dplyr's case when function that would look like:
iris %>%
filter(Species == "setosa") %>%
# Case when to cases
mutate(sub_a = case_when( Sepal.Length < 4.7~"A",
Sepal.Length < 5~ "B",
Sepal.Length < 5.2~ "C",
TRUE~"D")) %>%
# Collapse A and D
mutate(collapsed = ifelse(sub_a %in% c("A", "D"), "combined", sub_a)) %>%
ggplot(aes(collapsed, Petal.Length))+
geom_boxplot()
In OP comment the question was expanded to include creation of several other sub-classes. To solve this I will use the mutate function to make a few extra sub-categories, then use the gather function to pull them all into a single column while preserving the data within each subclass (e.g. keeping the counts correct).
iris %>%
filter(Species == "setosa") %>%
# Case when to cases
mutate(sub_a = case_when( Sepal.Length < 4.7~"A",
Sepal.Length < 5~ "B",
Sepal.Length < 5.2~ "C",
TRUE~"D")) %>%
# Collapse A and D
mutate(collapsed1 = ifelse(sub_a %in% c("A", "C"), "A+C", sub_a)) %>%
mutate(collapsed2 = ifelse(sub_a %in% c("A", "C", "D"), "A+C+D", sub_a)) %>%
# Pull all the new categories together into a new column called subclass
gather(new_cat, subclass, sub_a:collapsed2) %>%
# Filter to desired
filter(subclass %in% c("B", "A+C", "D", "A+C+D")) %>%
ggplot(aes(subclass, Petal.Length))+
geom_boxplot()