rggplot2grob

Change facet_wrap() strip positions to place facet strips inside plot


How can I change the facet_wrap() strip position as it has shown in below picture?
The data frames is from this question.
enter image description here


Solution

  • One option to achieve your desired result would be via the gggrid package. Similar to ggplot2::annotation_custom it allows to add grobs to a ggplot but offers much more flexibility, e.g. you could place different grobs to each facet panel. Moreover it allows to access the data and coords objects created by ggplot2 under the hood and allows to pass additional aesthetics.

    Basically it requires a function which creates the grob which are then added to the ggplot via gggrid::grid_panel. For the grob I use gridtext::richtext_grob which makes it easy to add a strip text like text box to each panel.

    library(ggplot2)
    library(gggrid)
    #> Loading required package: grid
    library(gridtext)
    
    set.seed(123)
    
    ID <- rep(c("ABC123", "DEF456", "GHI789", "JKL012"), each = 10)
    Vref <- c((runif(10, 1, 2)), (runif(10, 3, 5)), (runif(10, 6, 9)), (runif(10, 0, 2)))
    Time <- rep(c(1:10), 4)
    df <- data.frame(ID, Vref, Time)
    
    tg <- function(data, coords) {
      y_label <- max(coords$y) 
      gridtext::richtext_grob(data$label[which.max(coords$y)],
        x = unit(0, "npc")  + unit(.045, "npc"),
        y = unit(y_label, "npc") + unit(2, "mm"),
        hjust = 0,
        vjust = 0,
        valign = .5,
        padding = unit(rep(4.4, 4), "pt"),
        gp = grid::gpar(fontsize = 8, fill = "grey85"),
        box_gp = grid::gpar(col = "grey85")
      )
    }
    
    ggplot(df, aes(x = Time, y = Vref)) +
      geom_col() +
      scale_y_continuous(expand = expansion(mult = c(.05, .2))) +
      facet_wrap(~ID, nrow = 2) +
      gggrid::grid_panel(mapping = aes(label = ID), tg) +
      theme(strip.text = element_blank())