Skip to main content
AI in Production 2026 is now open for talk proposals.
Share insights that help teams build, scale, and maintain stronger AI systems.
items
Menu
  • About
    • Overview 
    • Join Us  
    • Community 
    • Contact 
  • Training
    • Overview 
    • Course Catalogue 
    • Public Courses 
  • Posit
    • Overview 
    • License Resale 
    • Managed Services 
    • Health Check 
  • Data Science
    • Overview 
    • Visualisation & Dashboards 
    • Open-source Data Science 
    • Data Science as a Service 
    • Gallery 
  • Engineering
    • Overview 
    • Cloud Solutions 
    • Enterprise Applications 
  • Our Work
    • Blog 
    • Case Studies 
    • R Package Validation 
    • diffify  

Setting the Graphics Device in a RMarkdown Document

Author: Colin Gillespie

Published: April 15, 2020

tags: r, graphics, markdown, rmarkdown, knitr, cairo

In our recent post about saving R graphics, it became obvious that achieving consistent graphics across platforms or even saving the “correct” graph on a particular OS was challenging. Getting consistent fonts across platforms often failed, and for the default PNG device under Windows, anti-aliasing was also an issue. The conclusion of the post was to use

  • grDevices::cairo_pdf() for saving PDF graphics or
  • grDevices::png(..., type = "cairo_png") for PNGs or alternatively
  • the new {ragg} package.

In many workflows, function calls to graphic devices are not explicit. Instead, the call is made by another package, such as {knitr}.

When kniting an Rmarkdown document, the default graphics device when creating PDF documents is grDevices::pdf() and for HTML documents it’s grDevices::png(). As we demostrated, these are the worst possible choices!

Do you use Professional Posit Products? If so, check out our managed Posit services

PDFs and PNGs

If you want to save your graphs as PDFs, then simply set

knitr::opts_chunk$set(dev = "cairo_pdf")

at the top of Rmarkdown file. The PNG variant is slightly different as we need to specify the device dev and also pass the type argument to the device

knitr::opts_chunk$set(dev = "png", dev.args = list(type = "cairo-png"))

These options, i.e. dev = "cairo_pdf", can also be set at individual chunks.

The {ragg} Package

Setting the agg_png() function from the {ragg} package as the graphics device is somewhat more tricky as it doesn’t come pre-defined within {knitr}. The {knitr} docs states that

if none of the 20 built-in devices is appropriate, we can still provide yet another name as long as it is a legal function name which can record plots (it must be of the form function(filename, width, height))

The arguments of agg_png() are

formals(ragg::agg_png)[1:3]
#> $filename
#> [1] "Rplot%03d.png"
#>
#> $width
#> [1] 480
#>
#> $height
#> [1] 480

This suggests we can simply set ragg::agg_png() as the {knitr} dev, as its of the correct form. However, careful reading of the knitr source code highlights that the dpi argument isn’t passed to new devices and that the units should be inches. So after a “little” experimentation, we have

ragg_png = function(..., res = 192) {
  ragg::agg_png(..., res = res, units = "in")
}
knitr::opts_chunk$set(dev = "ragg_png", fig.ext = "png")

Remember the dpi argument isn’t passed to ragg_png(), so if you want to change the resolution per chunk, then you will need to use

dev.args = list(ragg_png = list(res = 192))

As {ragg} is being developed by RStudio, I’m guessing that at some point in the near future, ragg will become native to {knitr}.


Jumping Rivers Logo

Recent Posts

  • Start 2026 Ahead of the Curve: Boost Your Career with Jumping Rivers Training 
  • Should I Use Figma Design for Dashboard Prototyping? 
  • Announcing AI in Production 2026: A New Conference for AI and ML Practitioners 
  • Elevate Your Skills and Boost Your Career – Free Jumping Rivers Webinar on 20th November! 
  • Get Involved in the Data Science Community at our Free Meetups 
  • Polars and Pandas - Working with the Data-Frame 
  • Highlights from Shiny in Production (2025) 
  • Elevate Your Data Skills with Jumping Rivers Training 
  • Creating a Python Package with Poetry for Beginners Part2 
  • What's new for Python in 2025? 

Top Tags

  • R (236) 
  • Rbloggers (182) 
  • Pybloggers (89) 
  • Python (89) 
  • Shiny (63) 
  • Events (26) 
  • Training (23) 
  • Machine Learning (22) 
  • Conferences (20) 
  • Tidyverse (17) 
  • Statistics (14) 
  • Packages (13) 

Authors

  • Amieroh Abrahams 
  • Shane Halloran 
  • Russ Hyde 
  • Myles Mitchell 
  • Tim Brock 
  • Theo Roe 
  • Colin Gillespie 
  • Aida Gjoka 
  • Gigi Kenneth 
  • Osheen MacOscar 
  • Sebastian Mellor 
  • Keith Newman 
  • Pedro Silva 

Keep Updated

Like data science? R? Python? Stan? Then you’ll love the Jumping Rivers newsletter. The perks of being part of the Jumping Rivers family are:

  • Be the first to know about our latest courses and conferences.
  • Get discounts on the latest courses.
  • Read news on the latest techniques with the Jumping Rivers blog.

We keep your data secure and will never share your details. By subscribing, you agree to our privacy policy.

Follow Us

  • GitHub
  • Bluesky
  • LinkedIn
  • YouTube
  • Eventbrite

Find Us

The Catalyst Newcastle Helix Newcastle, NE4 5TG
Get directions

Contact Us

  • hello@jumpingrivers.com
  • + 44(0) 191 432 4340

Newsletter

Sign up

Events

  • North East Data Scientists Meetup
  • Leeds Data Science Meetup
  • Shiny in Production
British Assessment Bureau, UKAS Certified logo for ISO 9001 - Quality management British Assessment Bureau, UKAS Certified logo for ISO 27001 - Information security management Cyber Essentials Certified Plus badge
  • Privacy Notice
  • |
  • Booking Terms

©2016 - present. Jumping Rivers Ltd