- If you got into the (bad) habit of using geom_histogram() to create bar charts, or geom_bar() to create histograms, you’ll need to switch.
- Layers are now much stricter about their arguments – you will get an error if you’ve supplied an argument that isn’t an aesthetic or a parameter. This breaks the handful of geoms/stats that used ... to pass additional arguments on to the underlying computation. Nowgeom_smooth()/stat_smooth() andgeom_quantile()/stat_quantile() use method.args instead; andstat_summary(), stat_summary_hex(), and stat_summary2d()use fun.args. This is likely to cause some short-term pain but in the long-term it will make it much easier to spot spelling mistakes and other errors.
- geom_text() has been overhauled to make labelling your data a little easier. You can use nudge_x and nudge_y arguments to offset labels from their corresponding points.check_overlap = TRUE provides a simple way to avoid overplotting of labels: labels that would otherwise overlap are omitted.ggplot(mtcars, aes(wt, mpg, label = rownames(mtcars))) + geom_point() + geom_text(nudge_y = 0.5, check_overlap = TRUE)

(Labelling points well is still a huge pain, but at least these new features make life a lit better.)
- geom_label() works like geom_text() but draws a rounded rectangle underneath each label:grid <- expand.grid( x = seq(-pi, pi, length = 50), y = seq(-pi, pi, length = 50)) %>% mutate(r = x ^ 2 + y ^ 2, z = cos(r ^ 2) * exp(-r / 6))ggplot(grid, aes(x, y)) + geom_raster(aes(fill = z)) + geom_label(data = data.frame(x = 0, y = 0), label = "Center") + theme(legend.position = "none") + coord_fixed()

- aes_() replaces aes_q(), and works like the SE functions in dplyr and my other recent packages. It supports formulas, so the most concise SE version of aes(carat, price) is nowaes_(~carat, ~price). You may want to use this form in packages, as it will avoid spurious R CMD check warnings about undefined global variables.ggplot(mpg, aes_(~displ, ~cty)) + geom_point()# Same asggplot(mpg, aes(displ, cty)) + geom_point()
AppearanceI’ve made a number of small tweaks to the default appearance:
- The default theme_grey() background colour has been changed from “grey90” to “grey92”: this makes the background a little less visually prominent.
- Labels and titles have been tweaked for readability. Axis labels are darker, and legend titles get the same visual treatment as axis labels.
- The default font size dropped from 12 to 11. You might be surprised that I’ve made the default text size smaller as it was already hard for many people to read. It turns out there was a bug in RStudio (fixed in 0.99.724), that shrunk the text of all grid based graphics. Once that was resolved the defaults seemed too big to my eyes.
- scale_size() now maps values to area, not radius. Usescale_radius() if you want the old behaviour (not recommended, except perhaps for lines). Continue to usescale_size_area() if you want 0 values to have 0 area.
- Bar and rectangle legends no longer get a diagonal line. Instead, the border has been tweaked to make it visible, and more closely match the size of line drawn on the plot.ggplot(mpg, aes(factor(cyl), fill = drv)) + geom_bar(colour = "black", size = 1) + coord_flip()

- geom_point() now uses shape 19 instead of 16. This looks much better on the default Linux graphics device. (It’s very slightly smaller than the old point, but it shouldn’t affect any graphics significantly). You can now control the width of the outline on shapes 21-25 with the stroke parameter.
- The default legend will now allocate multiple rows (if vertical) or columns (if horizontal) in order to make a legend that is more likely to fit on the screen. You can override with thenrow/ncol arguments to guide_legend()p <- ggplot(mpg, aes(displ,hwy, colour = manufacturer)) + geom_point() + theme(legend.position = "bottom")p# Revert back to previous behaviourp + guides(colour = guide_legend(nrow = 1))


- Two new themes were contributed by Jean-Olivier Irisson:theme_void() is completely empty and theme_dark() has a dark background designed to make colours pop out.
Facet labelsThanks to the work of Lionel Henry, facet labels have received three major improvements:
- You can switch the position of facet labels so they’re next to the axes.
- facet_wrap() now supports custom labellers.
- You can create combined labels when facetting by multiple variables.
Switching the labelsThe new switch argument allows you to switch the labels to display near the axes:
data <- transform(mtcars, am = factor(am, levels = 0:1, c("Automatic", "Manual")), gear = factor(gear, levels = 3:5, labels = c("Three", "Four", "Five")))ggplot(data, aes(mpg, disp)) + geom_point() + facet_grid(am ~ gear, switch = "both")
This is especially useful when the labels directly characterise the axes. In that situation, switching the labels can make the plot clearer and more readable. You may also want to use a neutral label background by setting strip.background to element_blank():
data <- mtcars %>% mutate( Logarithmic = log(mpg), Inverse = 1 / mpg, Cubic = mpg ^ 3, Original = mpg) %>% tidyr::gather(transformation, mpg2, Logarithmic:Original)ggplot(data, aes(mpg2, disp)) + geom_point() + facet_wrap(~transformation, scales = "free", switch = "x") + theme(strip.background = element_blank())