Dr. Alex Bajcz, Quantitative Ecologist, Minnesota Aquatic Invasive Species Research Center (MAISRC) 2026-06-29
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.






