4
votes

I'm trying to create a scatterplot where the points are jittered (geom_jitter), but I also want to create a black outline around each point. Currently I'm doing it by adding 2 geom_jitters, one for the fill and one for the outline:

beta <- paste("beta == ", "0.15")

ggplot(aes(x=xVar, y = yVar), data = data) + 
    geom_jitter(size=3, alpha=0.6, colour=my.cols[2]) + 
    theme_bw() + 
    geom_abline(intercept = 0.0, slope = 0.145950, size=1) + 
    geom_vline(xintercept = 0, linetype = "dashed") + 
    annotate("text", x = 2.5, y = 0.2, label=beta, parse=TRUE, size=5)+
    xlim(-1.5,4) + 
    ylim(-2,2)+
    geom_jitter(shape = 1,size = 3,colour = "black")

However, that results in something like this:

enter image description here

Because jitter randomly offsets the data, the 2 geom_jitters are not in line with each other. How do I ensure the outlines are in the same place as the fill points?

I've see threads about this (e.g. Is it possible to jitter two ggplot geoms in the same way?), but they're pretty old and not sure if anything new has been added to ggplot that would solve this issue

The code above works if, instead of using geom_jitter, I use the regular geom_point, but I have too many overlapping points for that to be useful

EDIT:

The solution in the posted answer works. However, it doesn't quite cooperate for some of my other graphs where I'm binning by some other variable and using that to plot different colours:

ggplot(aes(x=xVar, y = yVar, color=group), data = data) + 
    geom_jitter(size=3, alpha=0.6, shape=21, fill="skyblue") +
    theme_bw() +
    geom_vline(xintercept = 0, linetype = "dashed") +
    scale_colour_brewer(name = "Title", direction = -1, palette = "Set1") +
    xlim(-1.5,4) + 
    ylim(-2,2)

My group variable has 3 levels, and I want to colour each group level by a different colour in the brewer Set1 palette. The current solution just colours everything skyblue. What should I fill by to ensure I'm using the correct colour palette?

1
Could you jitter your data before ggplot()?Hugh

1 Answers

6
votes

You don't actually have to use two layers; you can just use the fill aesthetic of a plotting character with a hole in it:

# some random data
set.seed(47)
df <- data.frame(x = rnorm(100), y = runif(100))

ggplot(aes(x = x, y = y), data = df) + geom_jitter(shape = 21, fill = 'skyblue')

plot with light blue dots with black outlines

The colour, size, and stroke aesthetics let you customize the exact look.


Edit:

For grouped data, set the fill aesthetic to the grouping variable, and use scale_fill_* functions to set color scales:

# more random data
set.seed(47)
df <- data.frame(x = runif(100), y = rnorm(100), group = sample(letters[1:3], 100, replace = TRUE))

ggplot(aes(x=x, y = y, fill=group), data = df) + 
    geom_jitter(size=3, alpha=0.6, shape=21) +
    theme_bw() +
    geom_vline(xintercept = 0, linetype = "dashed") +
    scale_fill_brewer(name = "Title", direction = -1, palette = "Set1")

grouped scatterplot with outlined dots