Dr. Alex Bajcz, Quantitative Ecologist, Minnesota Aquatic Invasive Species Research Center (MAISRC) 2026-06-29

ggplotplus for?ggplot2 is an extraordinarily powerful graphics
package, used by perhaps millions to produce graphs for posters,
presentations, papers, and exploration. ggplotplus enhances
ggplot2 by:
Providing tools that override many of ggplot2’s
less-than-fully-accessible default design aspects so creating graphs
that adhere to design best practices is easier and quicker.
Enabling some design options–such as custom point shapes in
scatterplots, direct group labeling, and relocation of the y-axis
title–that are currently impossible via a single function call in
ggplot2.
Attempting to lower the learning curve and bandwidth required to
make high-quality, Universal-Design-oriented graphs, ready for
publication and sharing, using ggplot2.
In particular, ggplotplus is for anyone who wants or
needs to use ggplot2 but has limited time, skill, energy,
patience, experience, etc. with which to devote to learning its many
nuances. However, given its evidence-based approach to graph design, the
package is for everyone who wants to build defensible, maximally
consumable graphs quickly and with a fraction of the fiddly
customization often required to get a typical ggplot up to the most
exacting design standards. Plus, ggplotplus has a few
tricks to offer that, at present, aren’t available via a single function
call anywhere else–read on for details!
To begin using ggplotplus, first install the latest
development version from GitHub using the pak package:
# install.packages("devtools") #IF NOT ALREADY INSTALLED
pak::pak("MAISRC/ggplotplus")Or, alternatively, install the latest stable version from CRAN:
install.packages("ggplotplus")Then, load it alongside ggplot2:
# install.packages("ggplot2") #IF NOT ALREADY INSTALLED
library(ggplot2)
library(ggplotplus)Once loaded, you can start layering its _plus() tools
onto your ggplot2 calls to improve their design quickly and
with minimal effort!
Here’s a basic, default ggplot2 as a point of
comparison:
ggplot(iris,
mapping = aes(x = Petal.Length,
y = Sepal.Length)) +
geom_point(mapping = aes(color = Species)) 
The biggest single change you can make to the design of your graphs
via ggplotplus is via its theme_plus()
function, which overrides a suite of ggplot2’s default
design choices related to default color palettes, common geometry
layers, and layout parameters:
ggplot(iris,
mapping = aes(x = Petal.Length,
y = Sepal.Length)) +
geom_point(mapping = aes(color = Species)) +
theme_plus() #<--OVERHAULS THEME, GEOM, AND PALETTE RELATED DEFAULTS IN MANY WAYS. 
Do a quick comparison between this graph and the last one;
ggplotplus adjusts nearly every aspect’s of a ggplot’s
design in an effort to make them cleaner and more accessible.
If you want to add thoughtful gridlines, polish the appearance of
your continuous scales, and/or move your y-axis title to somewhere more
thoughtful and easier to read, add gridlines_plus(),
scale_continuous_plus(), and
yaxis_title_plus() to your calls, respective:
ggplot(iris,
mapping = aes(x = Petal.Length,
y = Sepal.Length)) +
geom_point(mapping = aes(color = Species)) +
theme_plus() +
scale_continuous_plus( #<--OVERHAULS AXIS BREAKS AND LIMITS (FOR CONTINUOUS SCALES ONLY!)
scale = "x",
name = "Petal length (cm)",
thin.labels = TRUE) +
scale_continuous_plus(
scale = "y",
name = "Sepal length (cm)") +
yaxis_title_plus() + #<--RELOCATES AND RE-ORIENTS Y AXIS TITLE.
gridlines_plus() + #<--ADDS THOUGHTFUL GRIDLINES, IF YOU *REALLY* WANT THEM.
labs(color = expression(italic("Iris")*" species")) #<--THIS IS BASE GGPLOT2, BUT A NICE TOUCH!
Notice how, in this version, gridlines are subtle but still legible, axes are more fully labelled, and the y-axis title is much easier to spot and read.
Rather than using a legend at all, you can use
direct_labels_plus() to label the groups directly within
the plotting area:
ggplot(iris,
mapping = aes(x = Petal.Length,
y = Sepal.Length)) +
geom_point(mapping = aes(color = Species)) +
theme_plus() +
scale_continuous_plus(
scale = "x",
name = "Petal length (cm)",
thin.labels = TRUE) +
scale_continuous_plus(
scale = "y",
name = "Sepal length (cm)") +
yaxis_title_plus() +
gridlines_plus() +
labs(color = expression(italic("Iris")*" species")) +
direct_labels_plus(data = iris, #<--HELP THE FUNCTION UNDERSTAND HOW YOUR DATA LOOK...
x = Petal.Length,
y = Sepal.Length,
group = Species) + #<--...AND WHAT VARIABLE DETERMINES THE GROUPS.
guides(color = "none") #<--OPTIONALLY, TURN THE LEGEND OFF.
With this approach, the legend becomes optional, saving space, increasing data density, and concentrating vital information close to where the reader most needs and expects it.
Another option: Call the reader’s attention to one or some of the
groups over others. scale_focus_plus() makes doing this
easy:
ggplot(iris,
mapping = aes(x = Petal.Length,
y = Sepal.Length)) +
geom_point(mapping = aes(color = Species)) +
theme_plus() +
scale_continuous_plus(
scale = "x",
name = "Petal length (cm)",
thin.labels = TRUE) +
scale_continuous_plus(
scale = "y",
name = "Sepal length (cm)") +
yaxis_title_plus() +
gridlines_plus() +
labs(color = expression(italic("Iris")*" species")) +
scale_focus_plus(aes = "color",
group_var = iris$Species, #<--HELP THE FUNCTION UNDERSTAND YOUR DATA.
focal_groups = "versicolor",
diff_nonfocal = TRUE #<--KEEP NON-FOCAL GROUPS DISTINCT.
)
In this version, our eyes can’t help but be drawn to the brightly colored group first, helping us to understand the message of your graph quicker.
ggplotplus also introduces a new palette of shapes
designed to be more distinctive than base R’s point shapes. Access these
via geom_point_plus():
ggplot(iris,
mapping = aes(x = Petal.Length,
y = Sepal.Length)) +
geom_point_plus( #<--SWITCH TO THIS FUNCTION TO ACCESS THE NEW SHAPES
mapping = aes(shape = Species, #<--YOU MUST MAP SHAPE HERE TO A VARIABLE OR CONSTANT
fill = Species),
chosen_shapes = c("squircle", #<--CHOOSE YOUR CUSTOM SHAPES, IF DESIRED.
"waffle",
"oval"),
alpha = 0.7
) +
theme_plus() +
scale_continuous_plus(
scale = "x",
name = "Petal length (cm)",
thin.labels = TRUE) +
scale_continuous_plus(
scale = "y",
name = "Sepal length (cm)") +
yaxis_title_plus() +
gridlines_plus() +
labs(fill = expression(italic("Iris")*" species"), #<--WE NEED BOTH FILL AND SHAPE SCALES TO MATCH IN NAME EXACTLY FOR THEM TO COLLAPSE INTO 1.
shape = expression(italic("Iris")*" species"))
The distinctiveness of these shapes makes them quick to distinguish, even without the aid of differing colors.
The above graphs demonstrates how ggplotplus’s tools
rethink the default design features of ggplot2. The
intention is to yield a more universal product more quickly so you can
spend less time fiddling with your graphs and more time sharing them
with a wider audience.
However, there’s a lot more to know! If you want to dive deeper, check out the full package cookbook.
ggplotplus is under active development. All current core
functions are expected to remain relatively stable, but some parameters,
features, and default settings may evolve, and addressing bugs,
inconsistencies, and gaps remains a high priority. User discretion and
feedback is advised! Please don’t hesitate to share bug reports or
questionable performance issues via the Issues feature on the package’s
Github page.
Thanks to Allan Cameron (@Allan Cameron) for answers to Stack Overflow
questions 79654995 and 79682150, which provided key coding elements
enabling the functionality of yaxis_title_plus() and
geom_point_plus(). Also, many thanks to Dr. Grant Vagle,
who frequently provided testing and feedback on the development of this
package.