rggplot2

Preventing errorbars to show through open points


I am using ggplot to generate a plot with points and errorbars. I would like to indicate whether the values are above or below 1 (variable trend) by changing the shape from filled to open and I also want to colour the points according to the variable treatment.

I tried to manually set the "fill" and "col" scales, but that didn't work:

plot1 <- ggplot(data = dat, aes(x = species, y = lambda, col = treatment, fill = trend)) +
  geom_abline(intercept = 1, slope = 0, linetype = "dashed") +
  geom_errorbar(aes(ymin = lower_BCPI_red, ymax = upper_BCPI_red), width = 0.2, position = position_dodge(width = 0.7)) +
  geom_point(position = position_dodge(width = 0.7), size = 4) +
  scale_color_manual(
    values = c("darkblue", "darkgreen"),
    labels = c("treat1" = "Treatment 1", "treat2" = "Treatment 2"),
    guide = guide_legend(order = 1)) +
  scale_fill_manual(
    values = c("white", "darkgreen"),
    labels = c("grow" = expression(paste(lambda, " > 1")), "shrink" = expression(paste(lambda, " < 1"))),
    guide = guide_legend(order = 2))

Plot 1

Then I tried to use shapes to characterize the variable trend instead, but the problem here is that if I use the open shape 21, the lines of the errorbars then show through the open points. I tried plotting some white points over the errorbars with the plan to then overlay the real points, but somehow the white and coloured points don't align (maybe of position dodge?).

plot2 <- ggplot(data = dat, aes(x = species, y = lambda, col = treatment, shape = trend)) +
  geom_abline(intercept = 1, slope = 0, linetype = "dashed") +
  geom_errorbar(aes(ymin = lower_BCPI_red, ymax = upper_BCPI_red), width = 0.2, position = position_dodge(width = 0.7)) +
  geom_point(position = position_dodge(width = 0.7), size = 4, col = "white", fill = "white") +
  geom_point(position = position_dodge(width = 0.7), size = 4) +
  scale_color_manual(
    values = c("darkblue", "darkgreen"),
    labels = c("treat1" = "Treatment 1", "treat2" = "Treatment 2"),
    guide = guide_legend(order = 1)) +
  scale_shape_manual(
    values = c(19, 21),
    labels = c("grow" = expression(paste(lambda, " > 1")), "shrink" = expression(paste(lambda, " < 1"))),
    guide = guide_legend(order = 2)) 

Plot 2

How can I plot points coloured according to the variable treatment and have open or filled points according to the variable trend without the errorbars showing through?

Data:

> dput(dat)
structure(list(species = c("spec2", "spec2", "spec1", "spec1"
), treatment = c("treat2", "treat1", "treat2", "treat1"), trend = c("grow", 
"grow", "grow", "shrink"), lambda = c(2.93041381166779, 2.02556855849611, 
1.26209237527084, 0.983136908926705), lower_BCPI_red = c(2.23364635527003, 
1.08955927540168, 1.02410220209615, 0.917503038357754), upper_BCPI_red = c(3.87343015758682, 
5.08404412887266, 1.40109042463976, 0.998656722552173)), row.names = c(NA, 
-4L), class = c("tbl_df", "tbl", "data.frame"))

Solution

  • Your second attempt was close. Forget duplicating the points. You just need to set fill. I used the color specified as panel.background in theme_grey.

    ggplot(data = dat, aes(x = species, y = lambda, col = treatment, shape = trend)) +
      geom_abline(intercept = 1, slope = 0, linetype = "dashed") +
      geom_errorbar(aes(ymin = lower_BCPI_red, ymax = upper_BCPI_red), width = 0.2, position = position_dodge(width = 0.7)) +
      geom_point(position = position_dodge(width = 0.7), size = 4, fill = "grey92") +
      scale_color_manual(
        values = c("darkblue", "darkgreen"),
        labels = c("treat1" = "Treatment 1", "treat2" = "Treatment 2"),
        guide = guide_legend(order = 1)) +
      scale_shape_manual(
        values = c(19, 21),
        labels = c("grow" = expression(lambda > 1), "shrink" = expression(lambda < 1)),
        guide = guide_legend(order = 2)) 
    

    resulting plot