rggplot2grob

Programmatically position image on ggplot using annotation_custom


I am trying to create a function (inside an R package) that adds an image to the lower right corner of a ggplot. Since this will be included in a R package, I want this function to programmatically position this image to the bottom right of the plot, without any user intervention.

Here is what I have so far:

# Setup
library(tidyverse)

get_png <- function(filename) {
  grid::rasterGrob(png::readPNG(filename), interpolate = TRUE)
}

# DaSL logo
l <- get_png("logo.png")

# Main function
add_dasl_logo <- function(logo) {
  list(annotation_custom(logo, xmin = 5, xmax = 7.5, ymin = 0, ymax = 15), 
       coord_cartesian(clip = "off"),
       theme(plot.margin = unit(c(1, 1, 3, 1), "lines"))
  )
}

# Plot
ggplot(mpg, aes(displ, hwy, colour = hwy)) +
  geom_point() +
  add_dasl_logo(l)

Image file (logo.png): enter image description here

Right now, the x-y min/max locations are manually set for this specific ggplot. I don't expect the average ggplot2 user to figure out the xmin, xmax, ymin, ymax coordinates.

How do I programmatically find these coordinates and use them in add_dasl_logo() without any user intervention?


Solution

  • Instead of setting the position for your logo in data coordinates via annotation_custom you could set the position in relative coordinates directly in grid::rasterGrob. This way the logo will be placed at the same position and with the same height and width for each plot.

    # Setup
    library(tidyverse)
    
    get_png <- function(filename) {
      grid::rasterGrob(png::readPNG(filename),
        interpolate = TRUE,
        x = unit(1, "npc") + unit(10, "pt"),
        y = unit(0, "npc") - unit(20, "pt"),
        height = unit(10, "pt"),
        hjust = 1,
        vjust = 1
      )
    }
    
    download.file("https://i.sstatic.net/uj2rP.png", "logo.png")
    
    # DaSL logo
    l <- get_png("logo.png")
    
    # Main function
    add_dasl_logo <- function(logo) {
      list(
        annotation_custom(logo),
        coord_cartesian(clip = "off"),
        theme(plot.margin = unit(c(1, 1, 3, 1), "lines"))
      )
    }
    
    ggplot(mpg, aes(displ, hwy, colour = hwy)) +
      geom_point() +
      add_dasl_logo(l)
    

    ggplot(mpg, aes(cty, hwy, colour = hwy)) +
      geom_point() +
      add_dasl_logo(l)