kjo kjo - 1 year ago 56
R Question

Adding outline color as point attribute

Here's a silly


df <- read.table(textConnection(
"pole medal bag x y
north gold paper 0.852 0.423
north gold plastic 0.277 0.055
north silver paper 0.257 0.211
north silver plastic 0.457 0.614
north bronze paper 0.825 0.299
north bronze plastic 0.672 0.126
south gold paper 0.482 0.764
south gold plastic 0.603 0.869
south silver paper 0.327 0.451
south silver plastic 0.147 0.672
south bronze paper 0.140 0.466
south bronze plastic 0.833 0.325
"), header = TRUE)

I know how to plot a scatterplot for these data in a way that uses color and shape to indicate two of the factor attributes; for example:

ggplot(data = df, aes(x = x, y = y)) +
geom_point(size = 4, aes(shape = pole, color = bag))

enter image description here

I would like to add one more point feature to indicate a third factor attribute (in this case
). The one possibility that comes to mind is a colored outline.

Is there a convenient way to do this? (One tricky aspect of the problem is that the color palette for the outlines must be distinct from that used for the point fills, because, for each point, the outline and the fill must be visually distinguishable.)


When I try Gregor's suggestion, the points look right, but the legend is messed up:

enter image description here

Answer Source

Yes you can! There is an example in the help for ?geom_point:

# For shapes that have a border (like 21), you can colour the inside and
# outside separately. Use the stroke aesthetic to modify the width of the
# border
ggplot(mtcars, aes(wt, mpg)) +
  geom_point(shape = 21, colour = "black", fill = "white", size = 5, stroke = 5)

In your case you'll want to use shapes 21 (circles with outline) and 24 (triangles with outline) like this:

ggplot(data = df, aes(x = x, y = y)) +
  geom_point(aes(shape = pole, color = medal, fill = bag),
             size = 4, stroke = 2) + 
  scale_shape_manual(values = c(21, 24))

Notice that, when using both, fill corresponds to the center of the points and color to the outline. You can change the weight of the outline by setting stroke.

As noted in the comments, you'll have to do some extra tweaking to get the legend right. Adding to the above plot:

fill_col = c("pink", "white")
outline_col = c("brown", "gold", "grey74")

scale_fill_manual(values = fill_col) + 
scale_color_manual(values = outline_col) +
guides(fill = guide_legend(override.aes = list(color = fill_col)),
       color = guide_legend(override.aes = list(shape = 21)))