ggplot2 3.0.0
Breaking changes
-
ggplot2 now supports/uses tidy evaluation (as described below). This is a
major change and breaks a number of packages; we made this breaking change
because it is important to make ggplot2 more programmable, and to be more
consistent with the rest of the tidyverse. The best general (and detailed)
introduction to tidy evaluation can be found in the meta programming
chapters in Advanced R.The primary developer facing change is that
aes()
now contains
quosures (expression + environment pairs) rather than symbols, and you'll
need to take a different approach to extracting the information you need.
A common symptom of this change are errors "undefined columns selected" or
"invalid 'type' (list) of argument" (#2610). As in the previous version,
constants (likeaes(x = 1)
oraes(colour = "smoothed")
) are stored
as is.In this version of ggplot2, if you need to describe a mapping in a string,
usequo_name()
(to generate single-line strings; longer expressions may
be abbreviated) orquo_text()
(to generate non-abbreviated strings that
may span multiple lines). If you do need to extract the value of a variable
instead userlang::eval_tidy()
. You may want to condition on
(packageVersion("ggplot2") <= "2.2.1")
so that your code can work with
both released and development versions of ggplot2.We recognise that this is a big change and if you're not already familiar
with rlang, there's a lot to learn. If you are stuck, or need any help,
please reach out on https://community.rstudio.com. -
Error: Column
y
must be a 1d atomic vector or a listInternally, ggplot2 now uses
as.data.frame(tibble::as_tibble(x))
to
convert a list into a data frame. This improves ggplot2's support for
list-columns (needed for sf support), at a small cost: you can no longer
use matrix-columns. Note that unlike tibble we still allow column vectors
such as returned bybase::scale()
because of their widespread use. -
Error: More than one expression parsed
Previously
aes_string(x = c("a", "b", "c"))
silently returned
aes(x = a)
. Now this is a clear error. -
Error:
data
must be uniquely named but has duplicate columnsIf layer data contains columns with identical names an error will be
thrown. In earlier versions the first occuring column was chosen silently,
potentially masking that the wrong data was chosen. -
Error: Aesthetics must be either length 1 or the same as the data
Layers are stricter about the columns they will combine into a single
data frame. Each aesthetic now must be either the same length as the data
frame or a single value. This makes silent recycling errors much less likely. -
Error:
coord_*
doesn't support free scalesFree scales only work with selected coordinate systems; previously you'd
get an incorrect plot. -
Error in f(...) : unused argument (range = c(0, 1))
This is because the
oob
argument to scale has been set to a function
that only takes a single argument; it needs to take two arguments
(x
, andrange
). -
Error: unused argument (output)
The function
guide_train()
now has an optional parameteraesthetic
that allows you to override theaesthetic
setting in the scale.
To make your code work with the both released and development versions of
ggplot2 appropriate, addaesthetic = NULL
to theguide_train()
method
signature.# old guide_train.legend <- function(guide, scale) {...} # new guide_train.legend <- function(guide, scale, aesthetic = NULL) {...}
Then, inside the function, replace
scale$aesthetics[1]
,
aesthetic %||% scale$aesthetics[1]
. (The %||% operator is defined in the
rlang package).# old setNames(list(scale$map(breaks)), scale$aesthetics[1]) # new setNames(list(scale$map(breaks)), aesthetic %||% scale$aesthetics[1])
-
The long-deprecated
subset
argument tolayer()
has been removed.
Tidy evaluation
-
aes()
now supports quasiquotation so that you can use!!
,!!!
,
and:=
. This replacesaes_()
andaes_string()
which are now
soft-deprecated (but will remain around for a long time). -
facet_wrap()
andfacet_grid()
now supportvars()
inputs. Like
dplyr::vars()
, this helper quotes its inputs and supports
quasiquotation. For instance, you can now supply faceting variables
like this:facet_wrap(vars(am, cyl))
instead of
facet_wrap(~am + cyl)
. Note that the formula interface is not going
away and will not be deprecated.vars()
is simply meant to make it
easier to create functions aroundfacet_wrap()
andfacet_grid()
.The first two arguments of
facet_grid()
becomerows
andcols
and now supportvars()
inputs. Note however that we took special
care to ensure complete backward compatibility. With this change
facet_grid(vars(cyl), vars(am, vs))
is equivalent to
facet_grid(cyl ~ am + vs)
, andfacet_grid(cols = vars(am, vs))
is
equivalent tofacet_grid(. ~ am + vs)
.One nice aspect of the new interface is that you can now easily
supply names:facet_grid(vars(Cylinder = cyl), labeller = label_both)
will give nice label titles to the facets. Of course,
those names can be unquoted with the usual tidy eval syntax.
sf
-
ggplot2 now has full support for sf with
geom_sf()
andcoord_sf()
:nc <- sf::st_read(system.file("shape/nc.shp", package = "sf"), quiet = TRUE) ggplot(nc) + geom_sf(aes(fill = AREA))
It supports all simple features, automatically aligns CRS across layers, sets
up the correct aspect ratio, and draws a graticule.
New features
-
ggplot2 now works on R 3.1 onwards, and uses the
vdiffr package for visual testing. -
In most cases, accidentally using
%>%
instead of+
will generate an
informative error (#2400). -
New syntax for calculated aesthetics. Instead of using
aes(y = ..count..)
you can (and should!) useaes(y = stat(count))
.stat()
is a real function
with documentation which hopefully will make this part of ggplot2 less
confusing (#2059).stat()
is particularly nice for more complex calculations because you
only need to specify it once:aes(y = stat(count / max(count)))
,
rather thanaes(y = ..count.. / max(..count..))
-
New
tag
label for adding identification tags to plots, typically used for
labelling a subplot with a letter. Add a tag withlabs(tag = "A")
, style it
with theplot.tag
theme element, and control position with the
plot.tag.position
theme setting (@thomasp85).
Layers: geoms, stats, and position adjustments
-
geom_segment()
andgeom_curve()
have a newarrow.fill
parameter which
allows you to specify a separate fill colour for closed arrowheads
(@hrbrmstr and @clauswilke, #2375). -
geom_point()
and friends can now take shapes as strings instead of integers,
e.g.geom_point(shape = "diamond")
(@daniel-barnett, #2075). -
position_dodge()
gains apreserve
argument that allows you to control
whether thetotal
width at eachx
value is preserved (the current
default), or ensure that the width of asingle
element is preserved
(what many people want) (#1935). -
New
position_dodge2()
provides enhanced dodging for boxplots. Compared to
position_dodge()
,position_dodge2()
comparesxmin
andxmax
values
to determine which elements overlap, and spreads overlapping elements evenly
within the region of overlap.position_dodge2()
is now the default position
adjustment forgeom_boxplot()
, because it handlesvarwidth = TRUE
, and
will be considered for other geoms in the future.The
padding
parameter adds a small amount of padding between elements
(@karawoo, #2143) and areverse
parameter allows you to reverse the order
of placement (@karawoo, #2171). -
New
stat_qq_line()
makes it easy to add a simple line to a Q-Q plot, which
makes it easier to judge the fit of the theoretical distribution
(@nicksolomon).
Scales and guides
-
Improved support for mapping date/time variables to
alpha
,size
,colour
,
andfill
aesthetics, includingdate_breaks
anddate_labels
arguments
(@karawoo, #1526), and newscale_alpha()
variants (@karawoo, #1526). -
Improved support for ordered factors. Ordered factors throw a warning when
mapped to shape (unordered factors do not), and do not throw warnings when
mapped to size or alpha (unordered factors do). Viridis is used as the
default colour and fill scale for ordered factors (@karawoo, #1526). -
The
expand
argument ofscale_*_continuous()
andscale_*_discrete()
now accepts separate expansion values for the lower and upper range
limits. The expansion limits can be specified using the convenience
functionexpand_scale()
.Separate expansion limits may be useful for bar charts, e.g. if one
wants the bottom of the bars to be flush with the x axis but still
leave some (automatically calculated amount of) space above them:ggplot(mtcars) + geom_bar(aes(x = factor(cyl))) + scale_y_continuous(expand = expand_scale(mult = c(0, .1)))
It can also be useful for line charts, e.g. for counts over time,
where one wants to have a ’hard’ lower limit of y = 0 but leave the
upper limit unspecified (and perhaps differing between panels), with
some extra space above the highest point on the line (with symmetrical
limits, the extra space above the highest point could in some cases
cause the lower limit to be negative).The old syntax for the
expand
argument will, of course, continue
to work (@huftis, #1669). -
scale_colour_continuous()
andscale_colour_gradient()
are now controlled
by global optionsggplot2.continuous.colour
andggplot2.continuous.fill
.
These can be set to"gradient"
(the default) or"viridis"
(@karawoo). -
New
scale_colour_viridis_c()
/scale_fill_viridis_c()
(continuous) and
scale_colour_viridis_d()
/scale_fill_viridis_d()
(discrete) make it
easy to use Viridis colour scales (@karawoo, #1526). -
Guides for
geom_text()
now accept custom labels with
guide_legend(override.aes = list(label = "foo"))
(@brianwdavis, #2458).
Margins
-
Strips gain margins on all sides by default. This means that to fully justify
text to the edge of a strip, you will need to also set the margins to 0
(@karawoo). -
Rotated strip labels now correctly understand
hjust
andvjust
parameters
at all angles (@karawoo). -
Strip labels now understand justification relative to the direction of the
text, meaning that in y facets, the strip text can be placed at either end of
the strip usinghjust
(@karawoo). -
Legend titles and labels get a little extra space around them, which
prevents legend titles from overlapping the legend at large font sizes
(@karawoo, #1881).
Extension points
-
New
autolayer()
S3 generic (@mitchelloharawild, #1974). This is similar
toautoplot()
but produces layers rather than complete plots. -
Custom objects can now be added using
+
if aggplot_add
method has been
defined for the class of the object (@thomasp85). -
Theme elements can now be subclassed. Add a
merge_element
method to control
how properties are inherited from the parent element. Add anelement_grob
method to define how elements are rendered into grobs (@thomasp85, #1981). -
Coords have gained new extension mechanisms.
If you have an existing coord extension, you will need to revise the
specification of thetrain()
method. It is now called
setup_panel_params()
(better reflecting what it actually does) and now
has argumentsscale_x
, andscale_y
(the x and y scales respectively)
andparam
, a list of plot specific parameters generated by
setup_params()
.What was formerly called
scale_details
(in coords),panel_ranges
(in layout) andpanel_scales
(in geoms) are now consistently called
panel_params
(#1311). These are parameters of the coord that vary from
panel to panel. -
ggplot_build()
andggplot_gtable()
are now generics, so ggplot-subclasses
can define additional behavior during the build stage. -
guide_train()
,guide_merge()
,guide_geom()
, andguide_gengrob()
are now exported as they are needed if you want to design your own guide.
They are not currently documented; use at your own risk (#2528). -
scale_type()
generic is now exported and documented. Use this if you
want to extend ggplot2 to work with a new type of vector.
Minor bug fixes and improvements
Faceting
-
facet_grid()
gives a more informative error message if you try to use
a variable in both rows and cols (#1928). -
facet_grid()
andfacet_wrap()
both give better error messages if you
attempt to use an unsupported coord with free scales (#2049). -
label_parsed()
works once again (#2279). -
You can now style the background of horizontal and vertical strips
independently withstrip.background.x
andstrip.background.y
theme settings (#2249).
Scales
-
discrete_scale()
documentation now inherits shared definitions from
continuous_scale()
(@alistaire47, #2052). -
guide_colorbar()
shows all colours of the scale (@has2k1, #2343). -
scale_identity()
once again produces legends by default (#2112). -
Tick marks for secondary axes with strong transformations are more
accurately placed (@thomasp85, #1992). -
Missing line types now reliably generate missing lines (with standard
warning) (#2206). -
Legends now ignore set aesthetics that are not length one (#1932).
-
All colour and fill scales now have an
aesthetics
argument that can
be used to set the aesthetic(s) the scale works with. This makes it
possible to apply a colour scale to both colour and fill aesthetics
at the same time, viaaesthetics = c("colour", "fill")
(@clauswilke). -
Three new generic scales work with any aesthetic or set of aesthetics:
scale_continuous_identity()
,scale_discrete_identity()
, and
scale_discrete_manual()
(@clauswilke). -
scale_*_gradient2()
now consistently omits points outside limits by
rescaling after the limits are enforced (@foo-bar-baz-qux, #2230).
Layers
-
geom_label()
now correctly produces unbordered labels whenlabel.size
is 0, even when saving to PDF (@bfgray3, #2407). -
layer()
gives considerably better error messages for incorrectly specified
geom
,stat
, orposition
(#2401). -
In all layers that use it,
linemitre
now defaults to 10 (instead of 1)
to better match base R. -
geom_boxplot()
now supplies a default value if nox
aesthetic is present
(@foo-bar-baz-qux, #2110). -
geom_density()
drops groups with fewer than two data points and throws a
warning. For groups with two data points, density values are now calculated
withstats::density
(@karawoo, #2127). -
geom_segment()
now also takes alinejoin
parameter. This allows more
control over the appearance of the segments, which is especially useful for
plotting thick arrows (@Ax3man, #774). -
geom_smooth()
now reports the formula used whenmethod = "auto"
(@davharris #1951).geom_smooth()
now orders by thex
aesthetic, making it
easier to pass pre-computed values without manual ordering (@izahn, #2028). It
also now knows it hasymin
andymax
aesthetics (#1939). The legend
correctly reflects the status of these
argument when used with stats
other than the default (@clauswilke, #1546). -
geom_tile()
now once again interpretswidth
andheight
correctly
(@malcolmbarrett, #2510). -
position_jitter()
andposition_jitterdodge()
gain aseed
argument that
allows the specification of a random seed for reproducible jittering
(@krlmlr, #1996 and @slowkow, #2445). -
stat_density()
has better behaviour if all groups are dropped because they
are too small (#2282). -
stat_summary_bin()
now understands thebreaks
parameter (@karawoo, #2214). -
stat_bin()
now accepts functions forbinwidth
. This allows better binning
when faceting along variables with different ranges (@botanize). -
stat_bin()
andgeom_histogram()
now sum correctly when using theweight
aesthetic (@jiho, #1921). -
stat_bin()
again uses correct scaling for the computed variablendensity
(@timgoodman, #2324). -
stat_bin()
andstat_bin_2d()
now properly handle thebreaks
parameter
when the scales are transformed (@has2k1, #2366). -
update_geom_defaults()
andupdate_stat_defaults()
allow American
spelling of aesthetic parameters (@foo-bar-baz-qux, #2299). -
The
show.legend
parameter now accepts a named logical vector to hide/show
only some aesthetics in the legend (@Tutuchan, #1798). -
Layers now silently ignore unknown aesthetics with value
NULL
(#1909).
Coords
-
Clipping to the plot panel is now configurable, through a
clip
argument
to coordinate systems, e.g.coord_cartesian(clip = "off")
(@clauswilke, #2536). -
Like scales, coordinate systems now give you a message when you're
replacing an existing coordinate system (#2264). -
coord_polar()
now draws secondary axis ticks and labels
(@dylan-stark, #2072), and can draw the radius axis on the right
(@thomasp85, #2005). -
coord_trans()
now generates a warning when a transformation generates
non-finite values (@foo-bar-baz-qux, #2147).
Themes
-
Complete themes now always override all elements of the default theme
(@has2k1, #2058, #2079). -
Themes now set default grid colour in
panel.grid
rather than individually
inpanel.grid.major
andpanel.grid.minor
individually. This makes it
slightly easier to customise the theme (#2352). -
Fixed bug when setting strips to
element_blank()
(@thomasp85). -
Axes positioned on the top and to the right can now customize their ticks and
lines separately (@thomasp85, #1899). -
Built-in themes gain parameters
base_line_size
andbase_rect_size
which
control the default sizes of line and rectangle elements (@karawoo, #2176). -
Default themes use
rel()
to set line widths (@baptiste). -
Themes were tweaked for visual consistency and more graceful behavior when
changing the base font size. All absolute heights or widths were replaced
with heights or widths that are proportional to the base font size. One
relative font size was eliminated (@clauswilke). -
The height of descenders is now calculated solely on font metrics and doesn't
change with the specific letters in the string. This fixes minor alignment
issues with plot titles, subtitles, and legend titles (#2288, @clauswilke).
Guides
-
guide_colorbar()
is more configurable: tick marks and color bar frame
can now by styled with argumentsticks.colour
,ticks.linewidth
,
frame.colour
,frame.linewidth
, andframe.linetype
(@clauswilke). -
guide_colorbar()
now useslegend.spacing.x
andlegend.spacing.y
correctly, and it can handle multi-line titles. Minor tweaks were made to
guide_legend()
to make sure the two legend functions behave as similarly as
possible (@clauswilke, #2397 and #2398). -
The theme elements
legend.title
andlegend.text
now respect the settings
ofmargin
,hjust
, andvjust
(@clauswilke, #2465, #1502). -
Non-angle parameters of
label.theme
ortitle.theme
can now be set in
guide_legend()
andguide_colorbar()
(@clauswilke, #2544).
Other
-
ggplot
gains a method forgrouped_df
s that adds a.group
variable,
which computes a unique value for each group. Use it with
aes(group = .group)
(#2351). -
ggproto()
produces objects with classc("ggproto", "gg")
, allowing for
a more informative error message when adding layers, scales, or other ggproto
objects (@jrnold, #2056). -
ggsave()
's DPI argument now supports 3 string options: "retina" (320
DPI), "print" (300 DPI), and "screen" (72 DPI) (@foo-bar-baz-qux, #2156).
ggsave()
now uses full argument names to avoid partial match warnings
(#2355), and correctly restores the previous graphics device when several
graphics devices are open (#2363). -
print.ggplot()
now returns the original ggplot object, instead of the
output fromggplot_build()
. Also, the object returned from
ggplot_build()
now has the class"ggplot_built"
(#2034). -
map_data()
now works even when purrr is loaded (#66). -
New functions
summarise_layout()
,summarise_coord()
, and
summarise_layers()
summarise the layout, coordinate systems, and layers
of a built ggplot object (#2034, @wch). This provides a tested API that
(e.g.) shiny can depend on. -
Updated startup messages reflect new resources (#2410, @mine-cetinkaya-rundel).