rggplot2bar-chart

Add two diagonal lines on top of y-axis ranging outside plot area to highlight truncation


I have a bar plot using ggplot() in which I have truncated the y-axis using coord_cartesian() so that differenes between the bars are more easily visible. In other words, the y-axis does not start at 0. I want to highlight this adjustment by adding two parallel diagonal lines in the lower end of the y-axis. How can I add these so that they are visible even in the negative quadrant?

Edit: Added snippet of data as well as example of what the result should look like:

  Trialcount Stimulus.ACC    N Stimulus.RT       sd        se        ci
1          1            0 1597    792.5792 310.2690  7.764008  15.22872
2          2            1   47   1061.4043 477.0400 69.583435 140.06419
3          3            0 1019    929.4210 385.5723 12.078659  23.70192
4          4            1  918    910.0447 373.0941 12.313941  24.16678
5          5            0  278   1115.7986 447.2075 26.821723  52.80031
6          6            1 1655    861.1704 342.7538  8.425260  16.52530
7          7            0 1019    929.4210 385.5723 12.078659  23.70192

Above data snippet as a tibble in R:

library(ggplot2)
library(tidyverse)
library(papaja)

rt_val_summary <- tibble(
  Trialcount = c(1, 2, 3, 4, 5, 6, 7),
  Stimulus.ACC = c(0, 1, 0, 1, 0, 1, 0),
  N = c(1597, 47, 1019, 918, 278, 1655, 1019),
  Stimulus.RT = c(792.5792, 1061.4043, 929.4210, 910.0447, 1115.7986, 861.1704, 929.4210),
  sd = c(310.2690, 477.0400, 385.5723, 373.0941, 447.2075, 342.7538, 385.5723),
  se = c(7.764008, 69.583435, 12.078659, 12.313941, 26.821723, 8.425260, 12.078659),
  ci = c(15.22872, 140.06419, 23.70192, 24.16678, 52.80031, 16.52530, 23.70192)
)

This is the plot so far:

RT_val_plot <- ggplot(data=rt_val_summary, aes(x=Trialcount, y = Stimulus.RT, fill = factor(Stimulus.ACC))) +
geom_bar(stat = "summary", position="dodge") +
scale_x_continuous(breaks = c(1,2,3,4,5,6,7)) +
labs(x = "Trial", y = "Reaction time (ms)") +
coord_cartesian(ylim = c(300, 1200)) +
scale_fill_manual(values=c("red", "green", "red", "green", "red", "green", "red", "green", "red", "green", "red", "green", "red", "green"),
name = "Valence", labels = c("negative", "positive")) +
geom_errorbar(aes(ymin=Stimulus.RT-se, ymax=Stimulus.RT+se), width =.1, position=position_dodge(.9)) +
geom_text(aes(label=paste("n =", N)), vjust=-0.5, position=position_dodge(0.9), size=3) +
geom_point(size = 2 , position=position_dodge(.9)) +
theme_apa()

And the following is a very raw, hand-drawn example of what my result should look like:

I tried different methods, e.g. adding lines using geom_segment() or annotation_custom() but these were only visible in the plot area (x&y>0). When setting clip=off in coord_cartesian(), this makes the bar plots visible in the area with y<0 as well, which I want to avoid


Solution

  • As I already mentioned in my comment one option would be to use a geom_rect which allows to limit the lower end of bars to the panel border. Hence, when setting clip="off" the bars will not reach beyond the panel border:

    library(ggplot2)
    
    ggplot(data = rt_val_summary, aes(x = Trialcount, y = Stimulus.RT, fill = factor(Stimulus.ACC))) +
      geom_rect(
        aes(
          xmin = after_stat(x - .45), xmax = after_stat(x + .45),
          ymin = after_stat(-Inf), ymax = after_stat(y)
        ),
        stat = "summary", position = "dodge"
      ) +
      scale_x_continuous(
        breaks = 1:7,
        expand = expansion(add = .5)
      ) +
      scale_y_continuous(
        expand = expansion(add = c(0, .5))
      ) +
      labs(x = "Trial", y = "Reaction time (ms)") +
      coord_cartesian(
        xlim = c(0.5, 7.5),
        ylim = c(300, 1200),
        clip = "off"
      ) +
      scale_fill_manual(
        values = c("red", "green"),
        name = "Valence",
        labels = c("negative", "positive")
      ) +
      geom_errorbar(
        aes(ymin = Stimulus.RT - se, ymax = Stimulus.RT + se),
        width = .1, position = position_dodge(.9)
      ) +
      geom_text(
        aes(label = paste("n =", N)),
        vjust = -0.5,
        position = position_dodge(0.9), size = 3
      ) +
      geom_point(size = 2, position = position_dodge(.9)) +
      annotate(
        geom = "segment",
        x = -.25, xend = .25,
        y = c(280, 300), yend = c(320, 340),
        color = "black"
      )
    #> No summary function supplied, defaulting to `mean_se()`