I am using the mpg dataset to replicate the issue I am having. I would like the color of the categorical axis car model to match the grouping variable car manufacturer. Ideally, the figure would have all of the car models produced by a manufacturer grouped together with a unique text color for each manufacturer (e.g., audi a4 with audi a4 quattro, both text color "blue" and hyundai tiburon with hyundai sonata, both text color "pink", etc.).
Example data
dat <- mpg[mpg$cyl == 4,]
unique(dat$manufacturer)
cols <- c("audi" = "#a6cee3", "chevrolet" = "#1f78b4", "dodge" = "#b2df8a",
"honda" = "#33a02c", "hyundai" = "#fb9a99","nissan" = "#e31a1c",
"subaru" = "#fdbf6f","toyota" = "#ff7f00","volkswagen" = "#cab2d6")
I have tried making the car model text color match the manufacturer by axis.text.y = element_text(size = 12, color = cols[dat$manufacturer]) but this does not work properly (it only uses 4 colors and they do not match the manufacturer). It also does not group like manufacturers together which would be ideal.
library(ggplot2)
ggplot(data = dat, aes(x = model, y = cty )) +
geom_point(shape = 21, size = 2, fill = "white") +
theme_bw() +
theme(panel.grid.major = element_line(colour = "gray85",linetype="longdash",size=0.1),
text = element_text(size = 14),
axis.text.x = element_text(size = 12, color = "black"),
axis.text.y = element_text(size = 12, color = cols[dat$manufacturer]),
legend.position = "none") +
coord_flip()
>Solution :
This could be achieved via the ggtext package which via the theme element element_markdown allows text styling via HTML and CSS. To this end wrap the model name in a span tag to which you add your desired font color via the style attribute:
Note: Your color vector was missing a color for subaru for which I added "purple".
library(ggplot2)
library(ggtext)
cols <- data.frame(manufacturer = names(cols), color = cols)
dat <- merge(dat, cols, by = "manufacturer", all.x = TRUE)
dat$model <- paste0("<span style=\"color: ", dat$color, "\">", dat$model, "</span>")
ggplot(data = dat, aes(x = model, y = cty )) +
geom_point(shape = 21, size = 2, fill = "white") +
theme_bw() +
theme(panel.grid.major = element_line(colour = "gray85",linetype="longdash",size=0.1),
text = element_text(size = 14),
axis.text.x = element_text(size = 12, color = "black"),
axis.text.y = ggtext::element_markdown(size = 12),
legend.position = "none") +
coord_flip()

EDIT To order by manufacturer you could first convert manufacturer to a factor with the levels set in your desired order. Afterwards order your data by manufacturer and convert the model column to a factor too which the order of the levels set according to the order in the re-arranged data. Last step could be achieved by using unique():
dat$manufacturer <- factor(dat$manufacturer,
levels = c("toyota", "audi", "chevrolet", "dodge", "honda",
"hyundai", "nissan", "subaru", "volkswagen"))
dat <- dat[order(dat$manufacturer), ]
dat$model <- factor(dat$model, levels = unique(dat$model))
ggplot(data = dat, aes(x = model, y = cty )) +
geom_point(shape = 21, size = 2, fill = "white") +
theme_bw() +
theme(panel.grid.major = element_line(colour = "gray85",linetype="longdash",size=0.1),
text = element_text(size = 14),
axis.text.x = element_text(size = 12, color = "black"),
axis.text.y = ggtext::element_markdown(size = 12),
legend.position = "none") +
coord_flip()
