diff --git a/NAMESPACE b/NAMESPACE index 1635857..c98d0ad 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -18,7 +18,6 @@ export(gtable_squash_cols) export(gtable_squash_rows) export(panel_border) export(plot_grid) -export(plot_theme) export(save_plot) export(theme_cowplot) export(theme_nothing) diff --git a/R/switch_axis.R b/R/switch_axis.R index a7e7398..604f31d 100644 --- a/R/switch_axis.R +++ b/R/switch_axis.R @@ -183,9 +183,9 @@ switch_axis_position <- function(plot, axis = c('y', 'x', 'xy'), keep = c('none' result } -#' Get theme of a ggplot2 plot -#' @param p The plot -#' @export +# Get theme of a ggplot2 plot +# @param p The plot +# @export plot_theme <- function(p) { plyr::defaults(p$theme, ggplot2::theme_get()) } diff --git a/inst/doc/axis_position.R b/inst/doc/axis_position.R index 09f1a9d..45b5076 100644 --- a/inst/doc/axis_position.R +++ b/inst/doc/axis_position.R @@ -3,20 +3,33 @@ require(cowplot) require(grid) # for unit() theme_set(theme_cowplot(font_size=12)) # reduce default font size p1 <- ggplot(mtcars, aes(mpg, disp)) + geom_line(colour = "blue") -p1 + theme_gray() + scale_y_continuous(position = "right") -p1 + theme_bw() + scale_x_continuous(sec.axis = dup_axis(name = waiver())) -p1 + scale_x_continuous(sec.axis = dup_axis()) + scale_y_continuous(sec.axis = dup_axis()) -p1 + theme(axis.ticks.length = unit(0.3, "cm"), + +# the following code only works for ggplot2 2.2.0 or later +if (packageVersion("ggplot2")>"2.1.0") + p1 + theme_gray() + scale_y_continuous(position = "right") + +if (packageVersion("ggplot2")>"2.1.0") + p1 + theme_bw() + scale_x_continuous(sec.axis = dup_axis(name = waiver())) + +if (packageVersion("ggplot2")>"2.1.0") + p1 + scale_x_continuous(sec.axis = dup_axis()) + scale_y_continuous(sec.axis = dup_axis()) + +if (packageVersion("ggplot2")>"2.1.0") + p1 + theme(axis.ticks.length = unit(0.3, "cm"), axis.text.x = element_text(margin = margin(0.2, unit = "cm"))) + scale_x_continuous(sec.axis = dup_axis()) + scale_y_continuous(sec.axis = dup_axis()) ## ---- message=FALSE, fig.width=4.25, fig.height=3------------------------ mtcars2 <- mtcars[1:15, ] mtcars2$name <- row.names(mtcars2) + +# the following code only works for ggplot2 2.2.0 or later +if (packageVersion("ggplot2")>"2.1.0"){ ggplot(mtcars2, aes(x = name, y = mpg, fill = name)) + geom_bar(stat = 'identity', position = "identity") + scale_y_reverse() + guides(fill = FALSE) + theme(axis.text.x = element_text(angle = 90, vjust=0.5, hjust=0)) + scale_x_discrete(position = "top") +} diff --git a/inst/doc/axis_position.Rmd b/inst/doc/axis_position.Rmd index 3f18cf9..4fe1114 100644 --- a/inst/doc/axis_position.Rmd +++ b/inst/doc/axis_position.Rmd @@ -17,10 +17,19 @@ require(cowplot) require(grid) # for unit() theme_set(theme_cowplot(font_size=12)) # reduce default font size p1 <- ggplot(mtcars, aes(mpg, disp)) + geom_line(colour = "blue") -p1 + theme_gray() + scale_y_continuous(position = "right") -p1 + theme_bw() + scale_x_continuous(sec.axis = dup_axis(name = waiver())) -p1 + scale_x_continuous(sec.axis = dup_axis()) + scale_y_continuous(sec.axis = dup_axis()) -p1 + theme(axis.ticks.length = unit(0.3, "cm"), + +# the following code only works for ggplot2 2.2.0 or later +if (packageVersion("ggplot2")>"2.1.0") + p1 + theme_gray() + scale_y_continuous(position = "right") + +if (packageVersion("ggplot2")>"2.1.0") + p1 + theme_bw() + scale_x_continuous(sec.axis = dup_axis(name = waiver())) + +if (packageVersion("ggplot2")>"2.1.0") + p1 + scale_x_continuous(sec.axis = dup_axis()) + scale_y_continuous(sec.axis = dup_axis()) + +if (packageVersion("ggplot2")>"2.1.0") + p1 + theme(axis.ticks.length = unit(0.3, "cm"), axis.text.x = element_text(margin = margin(0.2, unit = "cm"))) + scale_x_continuous(sec.axis = dup_axis()) + scale_y_continuous(sec.axis = dup_axis()) ``` @@ -30,11 +39,15 @@ It is also possible to use alternate discrete axes: ```{r, message=FALSE, fig.width=4.25, fig.height=3} mtcars2 <- mtcars[1:15, ] mtcars2$name <- row.names(mtcars2) + +# the following code only works for ggplot2 2.2.0 or later +if (packageVersion("ggplot2")>"2.1.0"){ ggplot(mtcars2, aes(x = name, y = mpg, fill = name)) + geom_bar(stat = 'identity', position = "identity") + scale_y_reverse() + guides(fill = FALSE) + theme(axis.text.x = element_text(angle = 90, vjust=0.5, hjust=0)) + scale_x_discrete(position = "top") +} ``` diff --git a/inst/doc/axis_position.html b/inst/doc/axis_position.html index 6cf3af6..c2d7fb8 100644 --- a/inst/doc/axis_position.html +++ b/inst/doc/axis_position.html @@ -79,25 +79,35 @@

2016-10-26

require(grid) # for unit() theme_set(theme_cowplot(font_size=12)) # reduce default font size p1 <- ggplot(mtcars, aes(mpg, disp)) + geom_line(colour = "blue") -p1 + theme_gray() + scale_y_continuous(position = "right") + +# the following code only works for ggplot2 2.2.0 or later +if (packageVersion("ggplot2")>"2.1.0") + p1 + theme_gray() + scale_y_continuous(position = "right")

-
p1 + theme_bw() + scale_x_continuous(sec.axis = dup_axis(name = waiver()))
+
if (packageVersion("ggplot2")>"2.1.0")
+  p1 + theme_bw() + scale_x_continuous(sec.axis = dup_axis(name = waiver()))

-
p1 + scale_x_continuous(sec.axis = dup_axis()) + scale_y_continuous(sec.axis = dup_axis())
+
if (packageVersion("ggplot2")>"2.1.0")
+  p1 + scale_x_continuous(sec.axis = dup_axis()) + scale_y_continuous(sec.axis = dup_axis())

-
p1 + theme(axis.ticks.length = unit(0.3, "cm"),
+
if (packageVersion("ggplot2")>"2.1.0")
+  p1 + theme(axis.ticks.length = unit(0.3, "cm"),
            axis.text.x = element_text(margin = margin(0.2, unit = "cm"))) +
      scale_x_continuous(sec.axis = dup_axis()) + scale_y_continuous(sec.axis = dup_axis())

It is also possible to use alternate discrete axes:

mtcars2 <- mtcars[1:15, ]
 mtcars2$name <- row.names(mtcars2)
+
+# the following code only works for ggplot2 2.2.0 or later
+if (packageVersion("ggplot2")>"2.1.0"){
 ggplot(mtcars2, aes(x = name, y = mpg, fill = name)) + 
   geom_bar(stat = 'identity', position = "identity") + 
   scale_y_reverse() +
   guides(fill = FALSE) +
   theme(axis.text.x = element_text(angle = 90, vjust=0.5, hjust=0)) +
-  scale_x_discrete(position = "top")
+ scale_x_discrete(position = "top") +}

diff --git a/inst/doc/introduction.html b/inst/doc/introduction.html index bfbe92f..bbe73b8 100644 --- a/inst/doc/introduction.html +++ b/inst/doc/introduction.html @@ -115,12 +115,15 @@

Arranging graphs into a grid

cowplot allows us to combine them into one graph via the function plot_grid():

plot_grid(plot.mpg, plot.diamonds, labels = c("A", "B"))
+

By default, the plots are simply placed into the grid as they are, and so the axes are not aligned. If axis alignment is required, it can be switched on via the align option:

plot_grid(plot.mpg, plot.diamonds, labels = c("A", "B"), align = "h")
-

Note that it is only possible to align graphs with the same internal structure. What this means is that you cannot align a faceted and a regular plot. You can align two faceted plots, but only if they have the same number of facets in the direction orthogonal to your alignment direction.

+

Note that it is only possible to align graphs with the same internal structure. What this means is that you cannot align a faceted and a regular plot. You can align two faceted plots, but only if they have the same number of facets in the direction orthogonal to your alignment direction.

The function plot_grid() will attempt to achieve a reasonable layout of the plots provided. However, you can precisely manipulate the layout by specifying the number of rows or columns or both:

plot_grid(plot.mpg, NULL, NULL, plot.diamonds, labels = c("A", "B", "C", "D"), ncol = 2)
+

plot_grid(plot.mpg, plot.diamonds, labels = c("A", "B"), nrow = 2, align = "v")
+

The function plot_grid() works nicely in combination with the function save_plot(), which can be told about the grid layout. For example, if we want to save a 2-by-2 figure, we might use this code:

plot2by2 <- plot_grid(plot.mpg, NULL, NULL, plot.diamonds,
                       labels=c("A", "B", "C", "D"), ncol = 2)
@@ -138,12 +141,14 @@ 

Generic plot annotations

ggdraw(plot.mpg) + 
   draw_plot_label("A", size = 14) + 
   draw_label("DRAFT!", angle = 45, size = 80, alpha = .2)
+

The function ggdraw() sets up the drawing layer, and functions that are meant to operate on this drawing layer all start with draw_. The resulting object is again a standard ggplot2 object, and you can do with it whatever you might do with a regular ggplot2 plot, such as save it with ggsave(). [However, as mentioned before, I recommend using save_plot() instead.]

In fact, because ggdraw() produces a standard ggplot2 object, we can draw on it with standard geoms if we want to. For example:

t <- (0:1000)/1000
 spiral <- data.frame(x = .45+.55*t*cos(t*15), y = .55-.55*t*sin(t*15), t)
 ggdraw(plot.mpg) + 
   geom_path(data = spiral, aes(x = x, y = y, colour = t), size = 6, alpha = .4)
+

I don’t know if this is useful in any way, but it shows the power of the approach.

Importantly, though, in all cases discussed so far, the main plot was below all other elements. Sometimes, you might want the plot on top. In this case, you can initialize an empty drawing canvas by calling ggdraw() without any parameters. You then place the plot by calling draw_plot(). Notice the difference in the two plots produced by the following code:

boxes <- data.frame(
@@ -157,15 +162,15 @@ 

Generic plot annotations

draw_plot(plot.mpg) + draw_label("Plot is on top of the grey boxes", x = 1, y = 1, vjust = 1, hjust = 1, size = 10, fontface = 'bold')
-
## Warning: Removed 1 rows containing missing values (geom_rect).
+
## Warning: Removed 4 rows containing missing values (geom_rect).
# plot below annotations
 ggdraw(plot.mpg) + 
   geom_rect(data = boxes, aes(xmin = x, xmax = x + .15, ymin = y, ymax = y + .15),
             colour = "gray60", fill = "gray80") + 
   draw_label("Plot is underneath the grey boxes", x = 1, y = 1,
             vjust = 1, hjust = 1, size = 10, fontface = 'bold')
-
## Warning: Removed 1 rows containing missing values (geom_rect).
-

+
## Warning: Removed 4 rows containing missing values (geom_rect).
+

Note that placing a plot on top of annotations only makes sense if the plot background is transparent. This is one of the main differences between theme_cowplot() and theme_classic(). If you tried the same example with theme_classic(), the gray boxes underneath the plot would not show.

Finally, the draw_plot() function also allows us to place graphs at arbitrary locations and at arbitrary sizes onto the canvas. This is useful for combining subplots into a layout that is not a simple grid, e.g. with one sub-plot spanning the entire width of the figure and two other figures using up half of the figure width:

plot.iris <- ggplot(iris, aes(Sepal.Length, Sepal.Width)) + 
@@ -178,7 +183,7 @@ 

Generic plot annotations

draw_plot(plot.mpg, 0, 0, .5, .5) + draw_plot(plot.diamonds, .5, 0, .5, .5) + draw_plot_label(c("A", "B", "C"), c(0, 0, 0.5), c(1, 0.5, 0.5), size = 15)
-

The functions background_grid() and panel_border() are convenience functions defined by cowplot to save some typing when manipulating the background grid and panel border.

+

The functions background_grid() and panel_border() are convenience functions defined by cowplot to save some typing when manipulating the background grid and panel border.

diff --git a/inst/doc/plot_annotations.html b/inst/doc/plot_annotations.html index b178152..fd2590e 100644 --- a/inst/doc/plot_annotations.html +++ b/inst/doc/plot_annotations.html @@ -84,13 +84,12 @@

Annotations underneath plots

Now we add an annotation underneath:

p2 <- add_sub(p1, "This is an annotation.\nAnnotations can span multiple lines.")
 ggdraw(p2)
-

+

Note that p2 is not a ggplot object but a gtable. It needs to be drawn with ggdraw().

We can also do this repeatedly, and we can use mathematical expressions instead of plain text. We just need to be aware that new annotations are added above previous ones:

p2 <- add_sub(p1, expression(paste(a^2+b^2, " = ", c^2)), size=12)
-p3 <- add_sub(p2, "This formula has no relevance here:", y  = 0, vjust = 0)
-

-
ggdraw(p3)
+p3 <- add_sub(p2, "This formula has no relevance here:", y = 0, vjust = 0) +ggdraw(p3)

This code also works with faceted plots:

plot.iris <- ggplot(iris, aes(Sepal.Length, Sepal.Width)) +
@@ -99,10 +98,11 @@ 

Annotations underneath plots

panel_border() # and a border around each panel p2 <- add_sub(plot.iris, "Annotation underneath a faceted plot, left justified.", x = 0, hjust = 0) ggdraw(p2)
-

+

Finally, it is possible to move the annotation inside of the plot if desired. Note that the coordinate x is measured relative to the left border of the plot panel but the coordinate y is measured relative to the space that has been added underneath the plot. Neither x nor y are measured in the units of the data plotted. This guarantees that the annotation can be placed in the same location in different plots, regardless of the data shown.

ggdraw(add_sub(p1, "Annotation inside plot", vpadding=grid::unit(0, "lines"),
        y = 6, x = 0.03, hjust = 0))
+

Annotations with mathematical expressions

@@ -113,6 +113,7 @@

Annotations with mathematical expressions

list(estimate = signif(c$estimate, 2), pvalue = signif(c$p.value, 2))) # adding label via ggdraw, in the ggdraw coordinates ggdraw(p1) + draw_label(label, .7, .9)
+

For the latter, we add draw_label() directly to the plot:

# adding label directly to plot, in the data coordinates
 p1 + draw_label(label, 20, 400, hjust = 0, vjust = 0)
@@ -126,9 +127,8 @@

Joint plot titles

p2 <- ggplot(mtcars, aes(x=hp, y=mpg)) + geom_point(colour = "green") + background_grid(minor='none') p <- plot_grid(p1, p2, labels=c('A', 'B')) # now add the title -title <- ggdraw() + draw_label("MPG declines with displacement and horsepower", fontface='bold') -

-
plot_grid(title, p, ncol=1, rel_heights=c(0.1, 1)) # rel_heights values control title margins
+title <- ggdraw() + draw_label("MPG declines with displacement and horsepower", fontface='bold') +plot_grid(title, p, ncol=1, rel_heights=c(0.1, 1)) # rel_heights values control title margins

In the final plot_grid line, the values of rel_heights need to be chosen appropriately so that the margins around the title look correct. With the values chosen here, the title takes up 9% (i.e., 0.1/1.1) of the total plot height.

diff --git a/inst/doc/plot_grid.html b/inst/doc/plot_grid.html index 7d5a178..bb1c263 100644 --- a/inst/doc/plot_grid.html +++ b/inst/doc/plot_grid.html @@ -84,12 +84,17 @@

Basic use of plot_grid()

plot.diamonds <- ggplot(diamonds, aes(clarity, fill = cut)) + geom_bar() + theme(axis.text.x = element_text(angle=70, vjust=0.5)) plot_grid(plot.mpg, plot.diamonds, labels = c('A', 'B')) +

If you specify the labels as labels="AUTO" or labels="auto" then labels will be auto-generated in upper or lower case, respectively:

plot_grid(plot.mpg, plot.diamonds, labels = "AUTO")
+

plot_grid(plot.mpg, plot.diamonds, labels = "auto")
+

By default, the plots are not aligned, but in many cases they can be aligned via the align option:

plot_grid(plot.mpg, plot.diamonds, labels = "AUTO", align = 'h')
+

plot_grid(plot.mpg, plot.diamonds, labels = "AUTO", ncol = 1, align = 'v')
+

In general, only plots that have the same number of visual elements can be aligned. Thus, a faceted and a non-faceted plot cannot be aligned. plot_grid() will know when it can and cannot align plots and will provide a warning in cases alignment is not possible:

plot.iris <- ggplot(iris, aes(Sepal.Length, Sepal.Width)) + 
   geom_point() + facet_grid(. ~ Species) + stat_smooth(method = "lm") +
@@ -99,6 +104,7 @@ 

Basic use of plot_grid()

align = 'v') # aligning does not work here
## Warning in align_plots(plotlist = plots, align = align): Graphs cannot be
 ## vertically aligned. Placing graphs unaligned.
+

In cases where plot_grid() cannot automatcially align plots, you can still align them manually if you have some knowledge of gtable, the internal layouting mechanism used by ggplot2. You simply have to convert both graphs into gtable objects and then adjust the relevant widths or heights. For the plot from the previous example, for example, you could do the following:

require(grid) # for unit.pmax(), unit.list()
 g.iris <- ggplotGrob(plot.iris) # convert to gtable
@@ -120,21 +126,25 @@ 

Basic use of plot_grid()

Fine-tuning the plot appearance

You can adjust the label size via the label_size option. Default is 14, so larger values will make the labels larger and smaller values will make them smaller:

plot_grid(plot.mpg, plot.diamonds, labels = "AUTO", align = 'h', label_size = 12)
+

Labels can be moved via the hjust and vjust options. More negative numbers move the labels to the right or up, respectively:

plot_grid(plot.mpg, plot.diamonds, labels = "AUTO", align = 'h', label_size = 12,
           hjust = -1, vjust = 2.5 )
+

It is possible to adjust individual labels one by one by passing vectors of adjustment values to the options hjust and vjust.

You can also adjust the relative widths and heights of rows and columns:

plot_grid(plot.mpg, plot.diamonds, labels = "AUTO", align = 'h', rel_widths = c(1, 1.3))
+

Finally, it is possible to scale the overall size of the plots up or down. This can be useful if the plots have too much or too little margin. Note that scale values >1 will not work if they move any part of a plot outside the entire plot area.

plot_grid(plot.mpg, plot.diamonds, labels = "AUTO", align = 'h', rel_widths = c(1, 1.3), scale = 0.95)
+

Nested plot grids

If you want to generate a plot arrangement that is not a simple grid, you may insert one plot_grid() plot into another:

bottom_row <- plot_grid(plot.mpg, plot.diamonds, labels = c('B', 'C'), align = 'h', rel_widths = c(1, 1.3))
 plot_grid(plot.iris, bottom_row, labels = c('A', ''), ncol = 1, rel_heights = c(1, 1.2))
-

+

(Notice how we used rel_heights to make to bottom row higher than the top row, and scale to introduce a little extra white-space around the plots. Also, we can’t auto-generate the labels in this case.) Alignment is a bit tricky in this case, though, and we won’t discuss this here. In principle, it can again be achieved by appropriately manipulating the underlying gtables.

diff --git a/inst/doc/shared_legends.html b/inst/doc/shared_legends.html index 8ca9f1b..2b705b0 100644 --- a/inst/doc/shared_legends.html +++ b/inst/doc/shared_legends.html @@ -98,7 +98,7 @@

2016-10-26

nrow = 1 ) prow
-

+

Legend to the side:

# extract the legend from one of the plots
 # (clearly the whole thing only makes sense if all plots
@@ -107,10 +107,9 @@ 

2016-10-26

# add the legend to the row we made earlier. Give it one-third of the width # of one plot (via rel_widths). -p <- plot_grid( prow, legend, rel_widths = c(3, .3))
-

-
p
-

+p <- plot_grid( prow, legend, rel_widths = c(3, .3)) +p +

Legend at the bottom:

# extract the legend from one of the plots
 # (clearly the whole thing only makes sense if all plots
@@ -119,10 +118,9 @@ 

2016-10-26

# add the legend underneath the row we made earlier. Give it 10% of the height # of one plot (via rel_heights). -p <- plot_grid( prow, legend_b, ncol = 1, rel_heights = c(1, .2))
-

-
p
-

+p <- plot_grid( prow, legend_b, ncol = 1, rel_heights = c(1, .2)) +p +

Legend between plots:

# arrange the three plots in a single row, leaving space between plot B and C
 prow <- plot_grid( p1 + theme(legend.position="none"),
@@ -137,7 +135,7 @@ 

2016-10-26

) prow + draw_grob(legend, 2/3.3, 0, .3/3.3, 1)
-

+

diff --git a/man/plot_theme.Rd b/man/plot_theme.Rd deleted file mode 100644 index 5c14a7b..0000000 --- a/man/plot_theme.Rd +++ /dev/null @@ -1,15 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/switch_axis.R -\name{plot_theme} -\alias{plot_theme} -\title{Get theme of a ggplot2 plot} -\usage{ -plot_theme(p) -} -\arguments{ -\item{p}{The plot} -} -\description{ -Get theme of a ggplot2 plot -} -