Part 59 Shape scales

library(ggplot2)
library(dplyr)
library(patchwork)

In addition to distinguishing groups or values by color, you can also distinguish groups by shape. You can see a list of R’s built-in plot shapes here.

You can use scale_shape_*() with discrete and binned variables, but not continuous variables.

R has a set of built-in plot shapes:

  • 0–14: Empty shapes — outline color, no fill
  • 15–20: Solid shapes — solid color, no separate fill - Default ggplot shape is 19
  • 21–25: Filled shapes — outline color, separate fill
ggplot(mtcars) +
  aes(x = hp, y = mpg, shape = factor(cyl)) +
  geom_point(size = 4, color = "blue", fill = "yellow") +
  scale_shape_manual(values = c(1, 19, 25)) +
  theme_minimal()

You can also give a character vector to plot those characters. Each element must be a single character long.

ggplot(mtcars) +
  aes(x = hp, y = mpg, shape = factor(cyl)) +
  geom_point(size = 4, color = "blue", fill = "yellow") +
  scale_shape_manual(values = c("4", "6", "8")) +
  theme_minimal()

mtcars |> 
  tibble::rownames_to_column(var = "model") |> 
  ggplot() +
  aes(x = hp, y = mpg, shape = factor(cyl), label = model) +
  geom_text(size = 4, color = "blue", fill = "yellow") +
  theme_minimal()

ggplot(mtcars) +
  aes(x = hp, y = mpg, shape = factor(cyl)) +
  geom_point(size = 4, color = "blue", fill = "yellow") +
  scale_shape_manual(values = c("😸", "😾", "🙀")) +
  theme_minimal()

scale_*_identity() is a special scale that uses the value of the variable directly on the plot. With shape, you can use it to plot the values if they are single character. (Use one of the text geoms if you want multi-character shapes.)

ggplot(mtcars) +
  aes(x = hp, y = mpg, shape = factor(cyl)) +
  geom_point(size = 4, color = "blue", fill = "yellow") +
  scale_shape_identity() +
  theme_minimal()

You can also use it with color or fill to store the color codes directly in the data.

tibble(
  scale = forcats::as_factor(c("ES", "A", "C", "Ex", "O")),
  score = c(5, 8, 4, 6, 3),
  .fill = c("#CD0BBC", "#DF536B", "#2297E6", "#61D04F", "#F5C710")
) %>% 
  ggplot() +
  aes(x = scale, y = score, fill = .fill) +
  geom_path(group = "n") + 
  geom_errorbar(aes(ymin = score - .5, ymax = score + .5), width = .05) +
  geom_point(shape = 21, size = 5) +
  scale_fill_identity() +
  ylim(0, 10) + 
  theme_minimal()