rloopsggplot2r-grid

Add logo to ggplot2 in a loop


I'm trying to utilize the method outlined here to add a logo to a plot, but in a loop. It works fine for one plot, but in a loop it doesn't print as expected. Note that the first R logo is placed prior to anything else, and then is dropped from the last plot.

enter image description here

I'm utilizing it in quarto to put out as a html document, though I don't think that should matter with the code.

---
title: "Logo Plot Question"
format: 
  html:
    page-layout: full
editor: source
execute:
  echo: false
  warning: false
editor_options: 
  chunk_output_type: console
---

```{r}
# Load ggplot2
library(ggplot2)
library(grid)
library(magick)

# # Create data
data <- data.frame(
  name=c("A","B","C","D","E") ,
  value=c(25,49,36,18,45)
  )

logo <- magick::image_read("https://upload.wikimedia.org/wikipedia/commons/thumb/1/1b/R_logo.svg/1448px-R_logo.svg.png")

for (i in 1:2){

  print("Start plot")
  
p <- ggplot(data, aes(name, value)) + 
     geom_bar(stat = "identity", width = 1,  aes(fill = value)) +
     coord_polar(clip = "off") +
     scale_y_continuous(limits = c(-10, 50)) +
     theme_void() +
     theme(legend.position = "none") +
     labs(title = paste0("Plot ", i))


grid::grid.raster(logo, x = 0.5, y = 0.5, 
                  just = c('center', 'top'),
                  width = unit(0.5, 'inches'))
print(p)

# Does not work...
# p2 <- grid::grid.raster(logo, x = 0.5, y = 0.5, 
#                   just = c('center', 'top'),
#                   width = unit(0.5, 'inches'))
# 
# print(p2)

print("End plot")

}
```

Note: I've seen solutions that suggest using ggsave() to save as an image and then reimport in. I would like to shy away from this as I am creating a report and don't want hundreds of images sitting around.


Solution

  • I like to keep ggplot objects as ggplot objects. The linked article draws over an existing ggplot.

    I would probably use a custom annotation in most cases, but this doesn't work with polar co-ordinates, so I would instead make a logo-only ggplot that I could add to any plot using the inset_element function from the patchwork package.

    library(ggplot2)
    library(grid)
    library(magick)
    library(patchwork)
    
    data <- data.frame(
      name=c("A","B","C","D","E") ,
      value=c(25,49,36,18,45)
    )
    
    logo_plot <- ggplot() +
      theme_void() +
      annotation_custom(rasterGrob( x = 0.5, y = 0.5,
        image_read(paste0("https://upload.wikimedia.org/wikipedia/",
                          "commons/thumb/1/1b/R_logo.svg/",
                          "1448px-R_logo.svg.png")), 
        just = c('center', 'center'), width = unit(0.5, 'inches')))
    
    for(i in 1:2) {
      
      cat("Here's plot", i, "\n")
      
      p <- ggplot(data, aes(name, value)) + 
        geom_bar(stat = "identity", width = 1,  aes(fill = value)) +
        coord_polar(clip = "off") +
        scale_y_continuous(limits = c(-10, 50)) +
        theme_void() +
        theme(legend.position = "none") +
        labs(title = paste0("Plot ", i)) +
        inset_element(logo_plot, 0, 0, 1, 1)
      
      print(p)
    }
    

    Now the Quarto output is:

    enter image description here