[magick]-ally adding images to figures

By Shannon Dunnigan

I create most of my data visualizations using R, which for most people seems like such a daunting task. Yes, R certainly has a learning curve, especially if you are not familiar with writing code, but there are so many cool things you can create using it!

We have talked about R on here before!

As I was creating a basic visualization of the sucralose and acetaminophen data we have collected from our Pellicer Creek SWMP site for an upcoming meeting, I thought it would be neat to be able to have our logo embedded into the plot.

If you want to know why we are interested in this information, drop a comment below!


After doing a bit of googling, I learned about this great package in R called ‘magick‘ – and it is magical. It is a package that simplifies image processing in R and has lots of functionality. I ended up using it to combine images.

Starting with the logo

For this code, I used ‘ggplot2’, ‘magick’, and ‘magrittr’ packages, which can all be downloaded from CRAN. Before running the code, I already produced the plot (from above) using another script and saved it as a .png file, which I cleverly named ‘plot1.png’.

With the ‘image_read’ function from ‘magick’, images can be read in directly from a file path, URL, or even as a raw vector with image data. Once the image has been read into R, there are a variety of things you can do with it. I have merely scaled down the image for the purposes of my plot, but you could cut, edit, apply filters and effects, etc.

If you are relatively new to R, in the code below, all of my comments are indicated with a pound (or hashtag) ‘#’ symbol. You can see my comments in each step of the code.

# Load the image you want to use
# ------------------------------------------------
logo_raw <- image_read(
  "C:/Users/Dunnigan_S/Documents/Dunnigan Documents/GTM - General.png")
# Scale down the logo (and other things)
## This is the cool part because you can do a lot to the
## image/logo before adding it to your final product
# -------------------------------------------------
logo <- logo_raw %>%
# Read in your plot
# -------------------------------------------------
plot1.1 <- image_read("plot1.png")
# Combine your plot with your logo
## The offset is what determines where your image will go on
## top of the plot
# -------------------------------------------------
out <- image_composite(plot1.1, logo, offset = "+10+1680")
# Save the plot you have created!
# -------------------------------------------------
image_write(out, "plot1.1.png")

Boom! Just a few lines of code (without my comments) and you have a logo on your plot!


Remember how I said that images can be read in from a URL? By using the great features of ‘magick’, I have indicated a potential cause of the spike in sucralose below…


“Wingardium leviosa” indeed, Mr. Potter.

And here is one of my favorite parts…

It works for .gif files, too! The animation component of .gifs means that we will need to set them as frames in an animation.

# Load image from URL
# -------------------------------------------------
logo_raw2 <- image_read(

# Set the plot as your background image
# -------------------------------------------------
background <- image_background(plot1.1, "white", flatten = TRUE)

# Combine and flatten frames
# -------------------------------------------------
frames <- image_composite(background, logo_raw2, offset = "+70+30")

# Turn frames into animation
## note that you can change the frames per second 'fps'
# -------------------------------------------------
animation <- image_animate(frames, fps = 5)

# Save the animated plot
# -------------------------------------------------
image_write(animation, "wand.gif")

See? Isn’t it magical?


Are you NERRd-y, too? If you use R and feel like trying out the ‘magick’ package, send along some of your creations! Daniel P. Hadley’s use of Vincent Vega in a graph is certainly one of my favorites…

4 Comments Add yours

  1. Kim says:

    This is great! Cool animation!

    I’ll bite – why do you want to know about sucralose and acetaminophen? I’m guessing they’re indicators of human wastewater… do you have any comparative values from less-impacted areas? Also, is that jump in acetaminophen from an increased detection limit?

    Liked by 1 person

    1. gtmresearch says:

      Great questions! Yes, we test for sucralose and acetaminophen because they are indicators of human wastewater (different stages of treatment), which is a concern of stakeholders in the area. We only test for these at this one station, so are unable to truly compare within our data sets, though we’ve been looking into other areas/agencies data. And yes, the detection limit increased from 0.004 to 0.008 ug/L for acetaminophen in 2017; good catch!

      Liked by 1 person

      1. Kim says:

        Interesting; thanks! Can you elaborate on the “different stages of treatment” part? Does the fact that you’re detecting sucralose and not acetaminophen indicate a certain stage in the wastewater treatment process, like septic inputs or something?

        I was involved in some work several years ago where we measured caffeine as in indicator of human influence; it’s a good marker, but really labor intensive to measure. Hopefully these two are easier.

        Liked by 1 person

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.