Jazz up your ggplots!
Useful tricks to elevate your data viz via `ggplot` extension packages in R
What's on this page

At Vizlab , we make fun and accessible data visualizations to communicate USGS research and data. Upon taking a closer look at some of our visualizations, you may think:
- “How can I add annotations to my chart?”
- “How can I use more custom effects in my chart design?”
- “How can I animate my chart?”
With the use of ggplot2
and ggplot2
extension packages we can customize our data visualizations with consistent syntax. Users can customize plot appearance in every way within the ggplot2
ecosystem, making chart design fully reproducible and reducing the need for external design software. Our water data visualization team, USGS VizLab, loves the customization that the ggplot ecosystem allows. For example, Hayley
added custom arrows and labels in this recently shared #DataViz
and Cee
added custom text directly onto this curved path of a recently shared-out animation
.
Here are some of our favorite functions and tricks to customize ggplot design, with complete code examples to try on your own. We demonstrate:
- Custom theme and fonts
- Arrows with
geom_curve
- Annotations with
geomtextpath
- Special effects with
ggfx
- Shapes with
ggimage
- Highlighting geom elements with
gghighlight
- Plot animation with
gganimate
- Chart composition with
cowplot
- Additional packages for custom chart design
- Takeaways
How to read this blog
As you read through this blog, you will find sections like this:
Click here
By clicking the icon on the left, data wrangling steps behind the example will unfold. This contains all of the packages and pre-plotting methods for each example.
To collapse the code chunk, simply click the icon again. In order to recreate the data visualizations in this blog post, you will need to run all code found in the collapsible chunks of data-wrangling steps. Additionally, you will need to install the following packages:
We are now ready to dig into some examples to jazz up your ggplots!
Add a custom theme and fonts to ggplot using theme
elements and showtext
One way to customize a plot is to utilize the built in theme
controls in ggplot2
. The theme
call allows users to choose custom colors, font size, background color, grid lines, etc. Here, we will utilize the showtext
package to load in free Google Fonts
and supply them in the theme controls.
Check out this documentation
for more details on customizable ggplot
theme elements.
Background on showtext
showtext
is a package developed by Qiu et al., 2022, that makes it easy to use various types of fonts in R graphs and supports most output formats of R graphics including PNG, PDF and SVG. For more information on showtext
see the package documentation
.
Add custom annotations and arrows to ggplot with geom_curve
![]() A preview of arrow created using | geom_curve allows users to draw a curved line such as the one seen in the example imate to the left. Using the waffle package, we will create waffle charts of Iron (Fe) groundwater contamination across 4 regions (West, Central, Midwest, and East) in the U.S. and add a custom arrow and annotation callout. |
geom_curve wrangling steps

A waffle chart of Iron (Fe) groundwater contaminant concentrations faceted by region (West, Central, Midwest, East).
Background on geom_curve
geom_curve
is a function included in the ggplot2
package developed by Wickham et al., 2019 that’s part of the tidyverse
. For more information on geom_curve
(and associated geom_segment
function) see the function documentation
.
Add annotations along a curved path with geomtextpath
![]() A preview of | Using the rnpn package, we will create a histogram of using spring leaf out data from the USA National Phenology Network
as of May 18, 2023, across CONUS. geomtextpath is used to label directly along a line, which can be seen in the example image to the left. Additional use cases of geomtextpath include adding labels to map contour lines, rivers and roads, trendlines and more. |
geomtextpath wrangling steps

Timing of spring leaf out in the contiguous U.S. as of May 18th, 2023. Data: USA National Phenology Network.
Check out this animated version with a map that displays current spring leaf out timing compared to the 30-year average with data from USA National Phenology Network.
Background on geomtextpath
geomtextpath
is a package developed by Allan Cameron and Teun van den Brand. This package makes use of existing text-based geom layers in ggplot
(i.e. geom_text
and geom_label
) and allows users to supply text that can follow any path. For more information on geomtextpath
see the package documentation
.
Apply filters and shaders on ggplot2
layers
You may have seen our reoccurring flow percentile visualizations that are shared out every month! These visualizations make use of the ggfx
package to add a shadow effect to the faceted state tile map and the national level tile. To create the national level streamflow conditions visualization, check out this repository
.

April 2023 streamflow conditions across the United States. Data: USGS Water Data for the Nation.
For this example, we will use the ggfx
package to plot streamflow percentiles at USGS streamgages relative to the historic record across California for the month of April. The cartogram will contain a shadow effect using ggfx::with_shadow()
demonstrated below.
ggfx wrangling steps
![]() April 2023 streamflow conditions in California using | ![]() April 2023 streamflow conditions in California with |
Background on ggfx
ggfx
is a package developed by Thomas Lin Pedersen that allows the use of various filters and shaders on ggplot2
layers. For more information on ggfx
see the package documentation
.
Add shapes with ggimage
![]() A preview of raindrop images mapped using | Designed to enhance data visualization capabilities by incorporating images into ggplot2 plots, ggimage allows users to map images to aesthetic elements such as points, bars, or polygons, providing a visually appealing way to represent data. Here, we will plot raindrop images using data from Heris et al., 2021
, to display mean rainfall intercepted by urban trees, with larger raindrops indicating states with greater urban tree interception. |
ggimage wrangling steps
The trick to using ggimage
with images that are scaled to data by size is to convert the data scale to something that is on the graphing scale. There are a couple ways to do this: one is to simply divide or multiply the size argument within the ggplot
geometry call by a constant value (e.g., geom_image(aes(size = I(data_value/3)))
). This works well for data that are relatively uniform in distribution (i.e., not skewed).
In the example here, mean rainfall intercepted by urban trees is very skewed, so we will use the quantiles of the values to transform the icon sizes into visually cohesive values (while still mapping to the real values). Otherwise, the states with relatively lower values of rainfall interception would be invisibly small and the values with higher rainfall would cover the whole plot.

Scatter plot with raindrop points showing mean annual intercepted rainfall (cubic meters) across CONUS.
Background on ggimage
ggimage
is a package developed by Guangchuang Yu that supports image files and graphic objects to be visualized in ggplot2
graphic system. For more information on ggimage
see the package documentation
.
Highlight geom elements with gghighlight
![]() A preview of | Using the gghighlight package in conjunction with ggplot2 , we’ll now plot snow water equivalent
data for a snow monitoring site in the Sierra Mountains of California. These data are from the U.S. Department of Agriculture Natural Resources Conservation Service Snow Telementry (SNOTEL) network, accessed using the snotelr package
. We’ll use gghighlight to highlight the data for water year
2023, which began October 1, 2022 and will continue until September 30, 2023. The image to the left previews gghighlight functionality by highlighting 2023 snow water equivalent, compared to 32 years of historic data (shown in gray). |
gghighlight wrangling steps

Snow water equivalent at the Leavitt Lake SNOTEL site in Mono County, California from 1990-2023.
Background on gghighlight
gghighlight
is a package developed by Hiroaki Yutani that can be used to highlight individual or multiple geometries within a ggplot2
plot. For more information on gghighlight
see the package documentation
.
Animate plots with gganimate
We can easily animate the plot we just made by using the gganimate
package. By adding just a couple of lines of code, we go from a static plot to a nifty gif!

Snow water equivalent at the Leavitt Lake SNOTEL site in Mono County, California from 1990-2023.
Background on gganimate
gganimate
is a package developed by Thomas Lin Pedersen and David Robinson that can be used to animate ggplot2
plots. For more information on gganimate
see the package documentation
.
Compose data viz with cowplot
As you may notice as you read through this blog, the Vizlab commonly uses cowplot
to compose our final data viz. This composition includes not only the ggplot
chart but also other common elements like annotation text and arrows, colored backgrounds, and/or images such as logos. We rely heavily on cowplot
’s functionality and flexibility when it comes to taking our viz from ggplot to its final, “production-ready” version.
We often start with cowplot
composition by first defining the canvas dimensions (example, a common Twitter canvas is 16:9, landscape) and color, the plot margins, and some other common aesthetics such as fonts and color schemes:
Then, we use the ggdraw()
function to combine the background canvas, plot, annotations, and logo. Here’s a simple template for that:
While cowplot
is extremely helpful, it can also be a bit frustrating to learn for beginners, so we have compiled a couple tips here and a future blog will go into much more detail. Here are some common tips for beginning cowplot
users:
- Some objects, such as
draw_plot()
anddraw_text()
default to the bottom left coordinates as (x = 0, y = 0) or (0,0). This means that a plot drawn withx = 0.5
andy = 0.5
would be positioned so that it’s lower left corner is in the center of the canvas. - Other objects, such as
draw_grob()
, which is a function used for rendering grid graphical objects (grobs
), default to the center of the canvas as (0,0). This means that those placed at (0.5, 0.5) would not be visible on the chart (they would be just off the canvas on the upper right hand side). To get thegrob
placed with its left corner in the plot center, you would need to definex = 0
andy = 0
. - Try to define your positioning and aesthetic elements (e.g., plot margins, color scheme, font types and sizes, etc) before the
ggdraw()
argument so that you any changes in those will be easily reflected throughout the whole cowplotggdraw()
call. - For advanced composition, you can use a
purrr::map()
function to create text, plot, or grobs that get placed more systematically. This is one of the advanced functions that we’ll highlight in a future blog. For now, there are examples of this in the04_historical_aaarcher
and28_trends_msleckman
folder in the github repository for chart challenge. - Finally, there is a bit of a trick to getting the ggplot text sizes to look good on the final composition with
cowplot
. Again, we recommend defining text sizes before building the ggplot items that will go intocowplot
so that you can easily iterate those sizes to get your final viz composition looking stellar.
Background on cowplot
cowplot
is a package developed by Claus O. Wilke that includes functions to align plots, arrange plots into complex compound figures, annotate plots, and mix plots with images. For more information on cowplot
see the package documentation
.
Additional packages for custom chart design
ggpattern
- Add custom
ggplot2
geoms that support filled areas with geometric and image-based patterns
- Add custom
ggrepel
- Supplies geoms for
ggplot2
to repel overlapping text labels
- Supplies geoms for
ggthemes
- Supplies
ggplot2
themes, geoms, and scales
- Supplies
colorBlindness
- Simulates color appearance with different color vision deficiencies
scico
- Palettes for R based on the Scientific Color-Maps .
Takeaways
The R community is filled with many creative contributors and developers who have helped data visualizations flourish! We hope you enjoyed these useful tricks to jazz up your ggplots by adding custom fonts, arrows, annotations, shapes and even filters/shader options. To view more of our recent data visualizations, check out our blog post on this year’s 30-Day Chart Challenge !
Any use of trade, firm, or product names is for descriptive purposes only and does not imply endorsement by the U.S. Government.
Categories:
Keywords:
Related Posts
The Hydro Network-Linked Data Index
November 2, 2020
Introduction updated 11-2-2020 after updates described here . updated 9-20-2024 when the NLDI moved from labs.waterdata.usgs.gov to api.water.usgs.gov/nldi/ The Hydro Network-Linked Data Index (NLDI) is a system that can index data to NHDPlus V2 catchments and offers a search service to discover indexed information.
Origin and development of a Snowflake Map
January 11, 2023
The result It’s been a snowy winter, so let’s make a snow cover map! This blog outlines the process of how I made a snowflake hex map of the contiguous U.
Reproducible Data Science in R: Iterate, don't duplicate
July 18, 2024
Overview This blog post is part of a series that works up from functional programming foundations through the use of the targets R package to create efficient, reproducible data workflows.
Reproducible Data Science in R: Writing better functions
June 17, 2024
Overview This blog post is part of a series that works up from functional programming foundations through the use of the targets R package to create efficient, reproducible data workflows.
Reproducible Data Science in R: Writing functions that work for you
May 14, 2024
Overview This blog post is part of a series that works up from functional programming foundations through the use of the targets R package to create efficient, reproducible data workflows.