Skip to content

Commit 59c503b

Browse files
committed
Merge pull request #1582 from hrbrmstr/master
Subtitles for ggplot2
2 parents 7edcea4 + 60d68fe commit 59c503b

28 files changed

+161
-55
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@
33
.RData
44
inst/doc
55
.httr-oauth
6+
.*.Rnb.cached

NEWS.md

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,22 @@
1-
# ggplot2 2.1.0.9000
1+
# ggplot2 2.1.0.9000
22

33
* `x` and `y` scales are now symmetric regarding the list of
44
aesthetics they accept: `xmin_final`, `xmax_final`, `xlower`,
55
`xmiddle` and `xupper` are now valid `x` aesthetics.
66

7+
* `ggtitle()` and `labs()` take a `subtitle` parameter which makes it
8+
possible to add a subtitle below the main plot title. (@hrbrmstr)
9+
10+
* `labs()` takes a `caption` parameter that will set the label for
11+
the annotation text below the plot panels. (@JanSchulz)
12+
13+
* The main plot title and subtitle are left-justified (`hjust = 0`) by
14+
default. The `caption` annotation below the plot will be right-justified
15+
by default. (@hrbrmstr)
16+
17+
* Minor code formatting issues in examples and function parameters were
18+
fixed. (@hrbrmstr)
19+
720
# ggplot2 2.1.0
821

922
## New features

R/coord-map.r

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@
4646
#'
4747
#' # Other projections
4848
#' nzmap + coord_map("cylindrical")
49-
#' nzmap + coord_map("azequalarea",orientation=c(-36.92,174.6,0))
49+
#' nzmap + coord_map("azequalarea", orientation = c(-36.92,174.6,0))
5050
#'
5151
#' states <- map_data("state")
5252
#' usamap <- ggplot(states, aes(long, lat, group = group)) +
@@ -71,7 +71,7 @@
7171
#'
7272
#' # World map, using geom_path instead of geom_polygon
7373
#' world <- map_data("world")
74-
#' worldmap <- ggplot(world, aes(x=long, y=lat, group=group)) +
74+
#' worldmap <- ggplot(world, aes(x = long, y = lat, group = group)) +
7575
#' geom_path() +
7676
#' scale_y_continuous(breaks = (-2:2) * 30) +
7777
#' scale_x_continuous(breaks = (-4:4) * 45)

R/geom-polygon.r

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,9 @@
3131
#' )
3232
#'
3333
#' # Currently we need to manually merge the two together
34-
#' datapoly <- merge(values, positions, by=c("id"))
34+
#' datapoly <- merge(values, positions, by = c("id"))
3535
#'
36-
#' (p <- ggplot(datapoly, aes(x=x, y=y)) + geom_polygon(aes(fill=value, group=id)))
36+
#' (p <- ggplot(datapoly, aes(x = x, y = y)) + geom_polygon(aes(fill = value, group = id)))
3737
#'
3838
#' # Which seems like a lot of work, but then it's easy to add on
3939
#' # other features in this coordinate system, e.g.:
@@ -43,7 +43,7 @@
4343
#' y = cumsum(runif(50,max = 0.1))
4444
#' )
4545
#'
46-
#' p + geom_line(data = stream, colour="grey30", size = 5)
46+
#' p + geom_line(data = stream, colour = "grey30", size = 5)
4747
#'
4848
#' # And if the positions are in longitude and latitude, you can use
4949
#' # coord_map to produce different map projections.

R/guide-colorbar.r

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@
7575
#' p1 + guides(fill = guide_colorbar(nbin = 100))
7676
#'
7777
#' # make top- and bottom-most ticks invisible
78-
#' p1 + scale_fill_continuous(limits = c(0,20), breaks=c(0, 5, 10, 15, 20),
78+
#' p1 + scale_fill_continuous(limits = c(0,20), breaks = c(0, 5, 10, 15, 20),
7979
#' guide = guide_colorbar(nbin=100, draw.ulim = FALSE, draw.llim = FALSE))
8080
#'
8181
#' # guides can be controlled independently

R/labels.r

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,12 @@ update_labels <- function(p, labels) {
1515
p
1616
}
1717

18-
#' Change axis labels and legend titles
18+
#' Change axis labels, legend titles, plot title/subtitle and below-plot
19+
#' caption.
1920
#'
20-
#' @param label The text for the axis or plot title.
21+
#' @param label The text for the axis, plot title or caption below the plot.
22+
#' @param subtitle the text for the subtitle for the plot which will be
23+
#' displayed below the title. Leave \code{NULL} for no subtitle.
2124
#' @param ... a list of new names in the form aesthetic = "new name"
2225
#' @export
2326
#' @examples
@@ -28,6 +31,15 @@ update_labels <- function(p, labels) {
2831
#' p + ylab("New y label")
2932
#' p + ggtitle("New plot title")
3033
#'
34+
#' # Can add a subtitle to plots with either of the following
35+
#' p + ggtitle("New plot title", subtitle = "A subtitle")
36+
#' p + labs(title = "New plot title", subtitle = "A subtitle")
37+
#'
38+
#' # Can add a plot caption underneath the whole plot (for sources, notes or
39+
#' # copyright), similar to the \code{sub} parameter in base R, with the
40+
#' # following
41+
#' p + labs(caption = "(based on data from ...)")
42+
#'
3143
#' # This should work independently of other functions that modify the
3244
#' # the scale names
3345
#' p + ylab("New y label") + ylim(2, 4)
@@ -38,7 +50,7 @@ update_labels <- function(p, labels) {
3850
#' p + labs(colour = "Cylinders")
3951
#'
4052
#' # Can also pass in a list, if that is more convenient
41-
#' p + labs(list(title = "Title", x = "X", y = "Y"))
53+
#' p + labs(list(title = "Title", subtitle = "Subtitle", x = "X", y = "Y"))
4254
labs <- function(...) {
4355
args <- list(...)
4456
if (is.list(args[[1]])) args <- args[[1]]
@@ -51,15 +63,17 @@ labs <- function(...) {
5163
xlab <- function(label) {
5264
labs(x = label)
5365
}
66+
5467
#' @rdname labs
5568
#' @export
5669
ylab <- function(label) {
5770
labs(y = label)
5871
}
72+
5973
#' @rdname labs
6074
#' @export
61-
ggtitle <- function(label) {
62-
labs(title = label)
75+
ggtitle <- function(label, subtitle = NULL) {
76+
labs(title = label, subtitle = subtitle)
6377
}
6478

6579
# Convert aesthetic mapping into text labels

R/plot-build.r

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,13 +250,29 @@ ggplot_gtable <- function(data) {
250250
title <- element_render(theme, "plot.title", plot$labels$title, expand_y = TRUE)
251251
title_height <- grobHeight(title)
252252

253+
# Subtitle
254+
subtitle <- element_render(theme, "plot.subtitle", plot$labels$subtitle, expand_y = TRUE)
255+
subtitle_height <- grobHeight(subtitle)
256+
257+
# whole plot annotation
258+
caption <- element_render(theme, "plot.caption", plot$labels$caption, expand_y = TRUE)
259+
caption_height <- grobHeight(caption)
260+
253261
pans <- plot_table$layout[grepl("^panel", plot_table$layout$name), ,
254262
drop = FALSE]
255263

264+
plot_table <- gtable_add_rows(plot_table, subtitle_height, pos = 0)
265+
plot_table <- gtable_add_grob(plot_table, subtitle, name = "subtitle",
266+
t = 1, b = 1, l = min(pans$l), r = max(pans$r), clip = "off")
267+
256268
plot_table <- gtable_add_rows(plot_table, title_height, pos = 0)
257269
plot_table <- gtable_add_grob(plot_table, title, name = "title",
258270
t = 1, b = 1, l = min(pans$l), r = max(pans$r), clip = "off")
259271

272+
plot_table <- gtable_add_rows(plot_table, caption_height, pos = -1)
273+
plot_table <- gtable_add_grob(plot_table, caption, name = "caption",
274+
t = -1, b = -1, l = min(pans$l), r = max(pans$r), clip = "off")
275+
260276
# Margins
261277
plot_table <- gtable_add_rows(plot_table, theme$plot.margin[1], pos = 0)
262278
plot_table <- gtable_add_cols(plot_table, theme$plot.margin[2])

R/position-dodge.r

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
#' # see ?geom_boxplot and ?geom_bar for more examples
1616
#'
1717
#' # To dodge items with different widths, you need to be explicit
18-
#' df <- data.frame(x=c("a","a","b","b"), y=2:5, g = rep(1:2, 2))
18+
#' df <- data.frame(x = c("a","a","b","b"), y = 2:5, g = rep(1:2, 2))
1919
#' p <- ggplot(df, aes(x, y, group = g)) +
2020
#' geom_bar(
2121
#' stat = "identity", position = "dodge",

R/quick-plot.r

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
#' \donttest{
3232
#' qplot(1:10, rnorm(10), colour = runif(10))
3333
#' qplot(1:10, letters[1:10])
34-
#' mod <- lm(mpg ~ wt, data=mtcars)
34+
#' mod <- lm(mpg ~ wt, data = mtcars)
3535
#' qplot(resid(mod), fitted(mod))
3636
#'
3737
#' f <- function() {
@@ -57,7 +57,7 @@
5757
#' qplot(factor(cyl), wt, data = mtcars, geom = c("boxplot", "jitter"))
5858
#' qplot(mpg, data = mtcars, geom = "dotplot")
5959
#' }
60-
qplot <- function(x, y = NULL, ..., data, facets = NULL, margins=FALSE,
60+
qplot <- function(x, y = NULL, ..., data, facets = NULL, margins = FALSE,
6161
geom = "auto", xlim = c(NA, NA),
6262
ylim = c(NA, NA), log = "", main = NULL,
6363
xlab = deparse(substitute(x)), ylab = deparse(substitute(y)),

R/scale-discrete-.r

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
#'
3131
#' # Use limits to adjust the which levels (and in what order)
3232
#' # are displayed
33-
#' d + scale_x_discrete(limits=c("Fair","Ideal"))
33+
#' d + scale_x_discrete(limits = c("Fair","Ideal"))
3434
#'
3535
#' # you can also use the short hand functions xlim and ylim
3636
#' d + xlim("Fair","Ideal", "Good")

R/scale-hue.r

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,16 @@
2121
#' d + scale_colour_hue(expression(clarity[beta]))
2222
#'
2323
#' # Adjust luminosity and chroma
24-
#' d + scale_colour_hue(l=40, c=30)
25-
#' d + scale_colour_hue(l=70, c=30)
26-
#' d + scale_colour_hue(l=70, c=150)
27-
#' d + scale_colour_hue(l=80, c=150)
24+
#' d + scale_colour_hue(l = 40, c = 30)
25+
#' d + scale_colour_hue(l = 70, c = 30)
26+
#' d + scale_colour_hue(l = 70, c = 150)
27+
#' d + scale_colour_hue(l = 80, c = 150)
2828
#'
2929
#' # Change range of hues used
30-
#' d + scale_colour_hue(h=c(0, 90))
31-
#' d + scale_colour_hue(h=c(90, 180))
32-
#' d + scale_colour_hue(h=c(180, 270))
33-
#' d + scale_colour_hue(h=c(270, 360))
30+
#' d + scale_colour_hue(h = c(0, 90))
31+
#' d + scale_colour_hue(h = c(90, 180))
32+
#' d + scale_colour_hue(h = c(180, 270))
33+
#' d + scale_colour_hue(h = c(270, 360))
3434
#'
3535
#' # Vary opacity
3636
#' # (only works with pdf, quartz and cairo devices)

R/stat-summary.r

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@
7070
#'
7171
#' # A set of useful summary functions is provided from the Hmisc package:
7272
#' stat_sum_df <- function(fun, geom="crossbar", ...) {
73-
#' stat_summary(fun.data=fun, colour="red", geom=geom, width=0.2, ...)
73+
#' stat_summary(fun.data = fun, colour = "red", geom = geom, width = 0.2, ...)
7474
#' }
7575
#' d <- ggplot(mtcars, aes(cyl, mpg)) + geom_point()
7676
#' # The crossbar geom needs grouping to be specified when used with
@@ -84,7 +84,7 @@
8484
#' if (require("ggplot2movies")) {
8585
#' set.seed(596)
8686
#' mov <- movies[sample(nrow(movies), 1000), ]
87-
#' m2 <- ggplot(mov, aes(x= factor(round(rating)), y=votes)) + geom_point()
87+
#' m2 <- ggplot(mov, aes(x = factor(round(rating)), y = votes)) + geom_point()
8888
#' m2 <- m2 + stat_summary(fun.data = "mean_cl_boot", geom = "crossbar",
8989
#' colour = "red", width = 0.3) + xlab("rating")
9090
#' m2

R/theme-defaults.r

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
#'
4343
#' @examples
4444
#' p <- ggplot(mtcars) + geom_point(aes(x = wt, y = mpg,
45-
#' colour=factor(gear))) + facet_wrap(~am)
45+
#' colour = factor(gear))) + facet_wrap(~am)
4646
#'
4747
#' p
4848
#' p + theme_gray()
@@ -126,8 +126,19 @@ theme_grey <- function(base_size = 11, base_family = "") {
126126
plot.background = element_rect(colour = "white"),
127127
plot.title = element_text(
128128
size = rel(1.2),
129+
hjust = 0,
129130
margin = margin(b = half_line * 1.2)
130131
),
132+
plot.subtitle = element_text(
133+
size = rel(0.9),
134+
hjust = 0,
135+
margin = margin(b = half_line * 0.9)
136+
),
137+
plot.caption = element_text(
138+
size = rel(0.9),
139+
hjust = 1,
140+
margin = margin(b = half_line * 0.9)
141+
),
131142
plot.margin = margin(half_line, half_line, half_line, half_line),
132143

133144
complete = TRUE

R/theme-elements.r

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,8 @@ el_def <- function(class = NULL, inherit = NULL, description = NULL) {
278278

279279
plot.background = el_def("element_rect", "rect"),
280280
plot.title = el_def("element_text", "title"),
281+
plot.subtitle = el_def("element_text", "title"),
282+
plot.caption = el_def("element_text", "title"),
281283
plot.margin = el_def("margin"),
282284

283285
aspect.ratio = el_def("character")

R/theme.r

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,14 @@ print.theme <- function(x, ...) utils::str(x)
187187
#' plot.background \tab background of the entire plot
188188
#' (\code{element_rect}; inherits from \code{rect}) \cr
189189
#' plot.title \tab plot title (text appearance)
190-
#' (\code{element_text}; inherits from \code{title}) \cr
190+
#' (\code{element_text}; inherits from \code{title})
191+
#' left-aligned by default\cr
192+
#' plot.subtitle \tab plot subtitle (text appearance)
193+
#' (\code{element_text}; inherits from \code{title})
194+
#' left-aligned by default\cr
195+
#' plot.caption \tab caption below the plot (text appearance)
196+
#' (\code{element_text}; inherits from \code{title})
197+
#' right-aligned by default\cr
191198
#' plot.margin \tab margin around entire plot
192199
#' (\code{unit} with the sizes of the top, right, bottom, and
193200
#' left margins) \cr
@@ -254,6 +261,11 @@ print.theme <- function(x, ...) utils::str(x)
254261
#' p + theme(plot.title = element_text(size = rel(2)))
255262
#' p + theme(plot.title = element_text(size = rel(2), colour = "blue"))
256263
#'
264+
#' # Add a subtitle and adjust bottom margin
265+
#' p + labs(title = "Vehicle Weight-Gas Mileage Relationship",
266+
#' subtitle = "You need to wrap long subtitleson manually") +
267+
#' theme(plot.subtitle = element_text(margin = margin(b = 20)))
268+
#'
257269
#' # Changing plot look with themes
258270
#' DF <- data.frame(x = rnorm(400))
259271
#' m <- ggplot(DF, aes(x = x)) +

R/utilities.r

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,8 @@ uniquecols <- function(df) {
7777
#' @param finite If \code{TRUE}, will also remove non-finite values.
7878
#' @keywords internal
7979
#' @export
80-
remove_missing <- function(df, na.rm=FALSE, vars = names(df), name="", finite = FALSE) {
80+
remove_missing <- function(df, na.rm = FALSE, vars = names(df), name = "",
81+
finite = FALSE) {
8182
stopifnot(is.logical(na.rm))
8283

8384
vars <- intersect(vars, names(df))

man/coord_map.Rd

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/geom_polygon.Rd

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/ggtheme.Rd

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/guide_colourbar.Rd

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)