Search code examples
rggplot2geom-text

How to add text outside a ggplot2 plot using npc coordinates in R


I am using a function in R to subset data and plot each of those subsets, and mapping (purrr::map) the function over a list of the subsets. I would like to be able to label the plots with a letter in the top left, in a position that remains constant despite the varying ranges of the axes. In other words, I want to use a normalized coordinate system, but I want to use negative values.

I have tried using ggpp::geom_text_npc(), which functions perfectly within the plot, but any values outside of the 0 to 1 range seem to just "round" to values inside the plot. For example:

library(tidyverse)
library(purrr)
library(ggpp)

datumz<-data.frame(ex = c(1:5, 11:15),
                   why = c(rep(1:5,2)),
                   kat = c(rep("a", 5),rep("b", 5)))
                   
selex<-list(c("a", "A"),
            c("b", "B"))
                  
grafz<-function(a){

  part<-datumz %>% 
    filter(kat==a[1])

  ggplot(part)+
    geom_point(mapping=aes(ex, why))+

    coord_cartesian(clip='off')+
    ggpp::geom_text_npc(size=8,aes(npcx=-.2, npcy=1.2, label=a[2]))
  
}

purrr::map(selex,grafz)

Places the text consistently across the two plots (which is good), but I can't find npcx or npcy values that would print outside of the plot box.


Solution

  • The patchwork package has some good functionality for figure tags. See below for how to add to 1) a set of combined figures with automatic sequencing, 2) a single figure with a custom tag, or 3) as a drop-in replacement for your ggpp::geom_text_npc line.

    library(patchwork)
    ggplot(subset(datumz, kat == "a"))+
      geom_point(mapping=aes(ex, why))+
      coord_cartesian(clip='off') +
    ggplot(subset(datumz, kat == "b"))+
      geom_point(mapping=aes(ex, why))+
      coord_cartesian(clip='off') +
      plot_annotation(tag_levels = "A")
    

    enter image description here

    Or if you want to make a single panel at a time:

    ggplot(subset(datumz, kat == "b"))+
      geom_point(mapping=aes(ex, why))+
      coord_cartesian(clip='off') +
      plot_annotation(tag_levels = list("B"))
    

    enter image description here

    So a drop-in replacement for your ggpp::geom_text_npc line could be:

    plot_annotation(tag_levels = list(a[2]))