0

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()
tassones
  • 891
  • 5
  • 18
  • another close approximation come from the last figure [on this page](https://cran.r-project.org/web/packages/ggpubr/readme/README.html) using ```ggpubr```. Still though, like manufacturers are not grouped together as would be ideal. – tassones Jun 24 '22 at 20:31

1 Answers1

4

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()

stefan
  • 90,330
  • 6
  • 25
  • 51
  • This is great! One last question, what if I wanted to change the order of the manufacturer groupings (e.g., Volkswagen at top and Toyota at the bottom)? – tassones Jun 24 '22 at 20:39
  • 1
    To order by manufacturer you have to convert to factors with the levels set in the desired order. Requires some fiddling but see my edit for an approach to achieve that. – stefan Jun 24 '22 at 20:57