Search code examples
rggplot2

Have legend show fill color AND have geom_points with black outline


In the figures below, I would like to have the legend show the fill color for the variable 'color'. I would also like all the points in the plot to have a black outline. It seems I can do one or the other but not both (i.e., legend has color and points have black outline). I have selected shapes that have a black outline, as can be seen in the 'cut' legend.

Similar SO questions:

Keeps black outline around points but legend is all black

library(tidyverse)

diamonds %>% 
  slice(1:20) %>% 
  ggplot(aes(x = x,
             y = y,
             shape = cut,
             fill = color)) +
  geom_point(size = 3,
             alpha = 0.8) +
  scale_shape_manual(values = c('Ideal' = 21,
                                'Premium' = 22,
                                'Good' = 23,
                                'Very Good' = 24,
                                'Fair' = 25)) +
  scale_fill_manual(values = c('E' = '#ca0020',
                               'F' = '#f4a582',
                               'H' = '#ffffbf',
                               'I' = '#92c5de',
                               'J' = '#0571b0')) +
  theme_bw()

Removes black outline around points but legend is all color

diamonds %>% 
  slice(1:20) %>% 
  ggplot(aes(x = x,
             y = y,
             shape = cut,
             fill = color,
             color = color)) +
  geom_point(size = 3,
             alpha = 0.8) +
  scale_shape_manual(values = c('Ideal' = 21,
                                'Premium' = 22,
                                'Good' = 23,
                                'Very Good' = 24,
                                'Fair' = 25)) +
  scale_fill_manual(values = c('E' = '#ca0020',
                               'F' = '#f4a582',
                               'H' = '#ffffbf',
                               'I' = '#92c5de',
                               'J' = '#0571b0')) +
  scale_color_manual(values = c('E' = '#ca0020',
                                'F' = '#f4a582',
                                'H' = '#ffffbf',
                                'I' = '#92c5de',
                                'J' = '#0571b0')) +
  theme_bw()

EDIT: I understand I can add a second, slightly larger set of points to sort of get a workaround but this is sloppy

diamonds %>% 
  slice(1:20) %>% 
  ggplot(aes(x = x,
             y = y,
             shape = cut,
             fill = color,
             color = color)) +
  geom_point(size = 3.5,
             alpha = 0.5,
             color = 'black') +
  geom_point(size = 3,
             alpha = 0.8) +
  scale_shape_manual(values = c('Ideal' = 21,
                                'Premium' = 22,
                                'Good' = 23,
                                'Very Good' = 24,
                                'Fair' = 25)) +
  scale_fill_manual(values = c('E' = '#ca0020',
                               'F' = '#f4a582',
                               'H' = '#ffffbf',
                               'I' = '#92c5de',
                               'J' = '#0571b0')) +
  scale_color_manual(values = c('E' = '#ca0020',
                                'F' = '#f4a582',
                                'H' = '#ffffbf',
                                'I' = '#92c5de',
                                'J' = '#0571b0')) +
  theme_bw()

Created on 2024-11-13 with reprex v2.1.1


Solution

  • You only need override the shape aesthetic of the points in the fill legend:

    slice(diamonds, 1:20) %>% 
      ggplot(aes(x, y, shape = cut, fill = color)) +
      geom_point(size = 3, alpha = 0.8) +
      scale_shape_manual(values = c(Ideal = 21, Premium = 22, Good  = 23,
                                    `Very Good` = 24, Fair = 25)) +
      scale_fill_manual(values = c('#ca0020', '#f4a582', '#ffffbf', 
                                   '#92c5de', '#0571b0'),
                        guide = guide_legend(override.aes = list(shape = 21))) +
      theme_bw()
    

    enter image description here