Search code examples
rggplot2facet-wrap

strip.position external in two columns facet_wrap plot


in two columns facet_wrap figures, it would be handy and nicer to have the name of the facet and the axis on the left for the left column, and on the right for the right column, in order to have a compact plot, with the facets close together.

ggplot(economics_long, aes(date, value)) +
  geom_line() +
  labs(y="") +
  facet_wrap(~variable, scales = "free_y", ncol = 2, strip.position = "left") +
       theme(strip.background = element_blank(), strip.placement = "outside")

current

as I wish it could it be


Solution

  • As far as I know, there is no way to do this in vanilla ggplot2. If you're comfortable with gtables, you might find the following doable.

    library(ggplot2)
    
    # Base plot
    p <- ggplot(economics_long, aes(date, value)) +
      geom_line() +
      labs(y="") +
      theme(strip.background = element_blank(), strip.placement = "outside")
    
    # Left aligned strips/axes
    left <- p +
      facet_wrap(~variable, scales = "free_y", ncol = 2, strip.position = "left")
    
    # Right aligned strips/axes
    right <- p +
      facet_wrap(~variable, scales = "free_y", ncol = 2, strip.position = "right") +
      scale_y_continuous(position = "right")
    
    # Convert to gtables
    left  <- ggplotGrob(left)
    right <- ggplotGrob(right)
    
    # Combine parts of left and right
    # Column numbers found by browsing through layout
    gt <- cbind(left[, 1:7], right[, 9:ncol(right)])
    
    # Render
    grid::grid.newpage(); grid::grid.draw(gt)
    

    Created on 2021-10-20 by the reprex package (v2.0.1)

    To find the panel positions in a more programmatically than judging the table layout manually, my best guess is to do this:

    panels_left  <- panel_cols(left)$l
    panels_right <- panel_cols(right)$l
    
    # The -2 is to include the left axis space (zero width because of absence) 
    # and the panel spacing
    gt <- cbind(left[, 1:panels_left[1]],
                right[, (panels_right[2]-2):ncol(right)])
    grid::grid.newpage(); grid::grid.draw(gt)