Search code examples
rggplot2reprex

R reprex not rendering correct ggplot output for very tall plots


When creating very tall horizontal bar plots with ggplot2, the plot rendered when using the package reprex cuts off some of the data, while the axis labels remain in the correct positions. This is not the same behavior as the ggplot output for the same code.

reprex output:

library(babynames)
library(dplyr)
library(ggplot2)
data("babynames")

bn <- babynames %>% 
  filter(year == 2015) %>% 
  arrange(-n) %>% 
  head(400) %>% 
  mutate(highlight = ifelse(n>12000, TRUE, FALSE)) %>% 
  arrange(name)

breaks <- bn %>% filter(highlight == TRUE) %>% pull(name)

ggplot(bn, aes(x=name, y=n, fill=highlight)) +
  geom_col() +
  scale_x_discrete(breaks = breaks)+
  coord_flip() +
  theme_classic()

Created on 2018-09-19 by the reprex package (v0.2.1)

Using ggsave() to save a png and upload it to stackoverflow:

ggsave("long_example.png",
       width = 4,
       height = 6,
       dpi=200)

bar for Abigail is now showing

In the ggsave() version, the highlighted bar for Abigail is appearing correctly, whereas the bottom few bars, including Abigail's, have disappeared in the reprex version. What's going on here?


Solution

  • As Nick Larsen pointed out, the problem is not that bottom bars are being dropped from the figure; it's that some bars within the chart and not being rendered when image dimensions and resolution are set at default values. The necessity of this behavior is an obvious example of the pigeonhole principle (if my bars were pigeons and pixels were holes). reprex is using knitr under the hood to create markdown output, and offers a syntax to modify these restrictive defaults via markdown chunk options (see more reprex examples here):

    reprex({
    
      #+ setup, include = FALSE
      knitr::opts_chunk$set(fig.width = 4, fig.height = 6, dpi = 200, warning = FALSE)
    
      #+ actual-reprex-code
      #{INSERT CODE HERE}
    
    }, venue = 'so')
    

    With figure options defined as above, there will be 1200 pixels of vertical space for my figure, easily enough to accommodate 400 bars and surrounding chart area. Substituting the example code from the question for {INSERT CODE HERE}, we get the desrired reprex output with the knitr code chunk options applied:

    library(babynames)
    library(dplyr)
    library(ggplot2)
    data("babynames")
    
    bn <- babynames %>% 
      filter(year == 2015) %>% 
      arrange(-n) %>% 
      head(400) %>% 
      mutate(highlight = ifelse(n > 12000, TRUE, FALSE)) %>% 
      arrange(name)
    
    breaks <- bn %>% filter(highlight == TRUE) %>% pull(name)
    
    ggplot(bn, aes(x = name, y = n, fill = highlight)) +
      geom_col() +
      scale_x_discrete(breaks = breaks)+
      coord_flip() +
      theme_classic()
    

    Created on 2018-09-21 by the reprex package (v0.2.1)