2

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?

Howard Baek
  • 186
  • 10

1 Answers1

3

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.stack.imgur.com/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)

stefan
  • 90,330
  • 6
  • 25
  • 51
  • Thank you for an awesome answer. I had a few followup questions: How did you determine the `unit` objects in the `x,y` arguments for `grid::rasterGrob()`? Also, on a similar note, what does `hjust = 1` and `vjust = 1` do? – Howard Baek May 29 '23 at 19:15
  • If I want to increase the size of the logo, do I increase the `height` argument in `grid::rasterGrob()`? – Howard Baek May 29 '23 at 19:16
  • 1
    Hi Howard. The x and y positions are explained easily. "npc" stands for native parent coordinates. In case of annotation custom the parent "grob" is the plot area. x = 1 will position the grob on the right border and y = 0 at the bottom border of the parent aka the plot area. `hjust=1` (as e.g. in geom_text). will align the logo to the right of the specified position, and `vjust=1` align on the top. Additionally I shifted the logo a bit in the x and y direction, i.e. the 10 and 20 are probably not the best choices and may need some adjustment if your change the size of the logo. – stefan May 29 '23 at 19:28
  • 1
    ... and yup. You could adjust the size using ´height` and/or `width`. – stefan May 29 '23 at 19:28