Jaeoc
Jaeoc

Reputation: 65

ggplot2 show layered points correctly in legend with several groupings

I wish to indicate certain points in my plot both by color and by circling them (for black and white viewing). I am already using the shape parameter for a separate grouping, but can do this by using two geom_point layers. Unfortunately I cannot figure out how to get the legend to correspond to my points. Here is a minimal example to show what I mean:

x <- data.frame(names = rep(letters[1:24],2), 
            grouping1 = factor(rep(c("Treatment", "Control"), each = 24)),
            grouping2 = factor(rep(rep(c("Matched","Unmatched"), each = 12), 2)), 
            values1 = runif(48, 60, 120), values2 = runif(48, 11, 25))


ggplot(data = x, aes(x = values1, y = values2, group = names)) +
     geom_point(aes(shape = grouping1, color = grouping2)) +
     geom_line(alpha = 0.2) +
     geom_point(data = x[x$grouping1 == 1 & x$grouping2 == 1,], aes(values1, values2), 
                shape = 21, size = 3, show.legend = TRUE)

If I include show.legend = TRUE as above this circles everything in the legend. I would like only the red points (as in the graph) to be circled by a border in the legend as well. Thankful for any help.enter image description here

Upvotes: 2

Views: 1304

Answers (2)

aosmith
aosmith

Reputation: 36114

You can get pretty close to what you want if you use fillable points. That way you can you can map both fill and color scales to grouping2. This makes it so only the one legend is affected by the additional geom_point layer. You can then modify the legend to remove the circle for the second group using override.aes in guide_legend.

I used override.aes to keep a filled point shape legend, as well, as using fillable points changes what the shape legend looks like by default.

Here's one option, where the surrounding circle is the same color as the points:

ggplot(data = x, aes(x = values1, y = values2, group = names)) +
    geom_point(aes(shape = grouping1, fill = grouping2, colour = grouping2)) +
    geom_line(alpha = 0.2) +
    geom_point(data = x[x$grouping1 == 1 & x$grouping2 == 1,], 
               aes(values1, values2, color = grouping2),
               shape = 1, size = 3 ) +
    scale_shape_manual(values = c(21, 24) ) + # fillable shapes
    guides(fill = guide_legend(override.aes = list(color = c("#F8766D", NA),
                                                   shape = 21) ),
           shape = guide_legend(override.aes = list(fill = "black") ) )

enter image description here

A subtly different option, keeping the circle around the points black. However, it also puts a black outline on the filled points (i.e., makes the "stroke" color black). The stroke color of the other group is kept the same as the fill color.

ggplot(data = x, aes(x = values1, y = values2, group = names)) +
    geom_point(aes(shape = grouping1, fill = grouping2, colour = grouping2)) +
    geom_line(alpha = 0.2) +
    geom_point(data = x[x$grouping1 == 1 & x$grouping2 == 1,], 
               aes(values1, values2, color = grouping2),
               shape = 21, size = 3 ) +
    scale_shape_manual(values = c(21, 24) ) +
    scale_color_manual(values = c("black", "#00BFC4") ) +
    guides(fill = guide_legend(override.aes = list(color = c("black", NA),
                                                   shape = 21) ),
           shape = guide_legend(override.aes = list(fill = "black") ) )

enter image description here

Upvotes: 1

Jan Boyer
Jan Boyer

Reputation: 1580

If you combine your two groups, it's simpler to get them all in the legend

x$bothgroups <- paste(x$grouping1, x$grouping2)    

Then use shapes 21 - 25, which have color and fill characteristics. That way, you can set color to use black for the points you want circled, creating a dark outline, and use the same color as fill for points you don't want circled, so they show up as solid color points without outlines.

ggplot(data = x, aes(x = values1, y = values2, group = names)) +
  geom_point(aes(shape = bothgroups, color = bothgroups, fill = bothgroups,
                 stroke = 1.5)) + #make border thicker so it is visible
  geom_line(alpha = 0.2) +
  scale_shape_manual(values = c(21, 24, 21, 21)) + #circle triangle circle circle
  #fill sets color in center of points
  scale_fill_manual(values = c("green", "green", "tomato", "green")) +
  #color sets outline color - match to fill for points you don't want circled
  scale_color_manual(values = c("green", "green", "black", "black"))

enter image description here

Upvotes: 1

Related Questions