From e743b1e18ef4d5360259ca90ba59d0de48ef8d68 Mon Sep 17 00:00:00 2001 From: Claus Wilke Date: Fri, 20 Oct 2017 14:59:24 -0500 Subject: [PATCH] improved vignette --- inst/doc/axis_position.html | 4 +-- inst/doc/introduction.R | 24 +++++++++++++++++ inst/doc/introduction.Rmd | 36 ++++++++++++++++++++++++- inst/doc/introduction.html | 48 +++++++++++++++++++++++++--------- inst/doc/plot_annotations.html | 16 ++++++------ inst/doc/plot_grid.html | 30 ++++++++++----------- inst/doc/shared_legends.html | 14 +++++----- vignettes/introduction.Rmd | 36 ++++++++++++++++++++++++- 8 files changed, 162 insertions(+), 46 deletions(-) diff --git a/inst/doc/axis_position.html b/inst/doc/axis_position.html index 1ea1ed3..67c6adc 100644 --- a/inst/doc/axis_position.html +++ b/inst/doc/axis_position.html @@ -12,7 +12,7 @@ - + Changing the axis positions @@ -70,7 +70,7 @@

Changing the axis positions

Claus O. Wilke

-

2017-08-13

+

2017-10-20

diff --git a/inst/doc/introduction.R b/inst/doc/introduction.R index 7fd6d11..2109eae 100644 --- a/inst/doc/introduction.R +++ b/inst/doc/introduction.R @@ -133,3 +133,27 @@ ggdraw() + theme(legend.justification = "top"), 0.5, 0.52, 0.5, 0.4) + draw_plot_label(c("A", "B"), c(0, 0.5), c(1, 0.92), size = 15) +## ----message=FALSE------------------------------------------------------- +p <- ggplot(iris, aes(x=Sepal.Length, fill=Species)) + geom_density(alpha = 0.7) +ggdraw() + + draw_image("http://jeroen.github.io/images/tiger.svg") + + draw_plot(p) + +## ----message=FALSE, results="hide"--------------------------------------- +img <- magick::image_read("http://jeroen.github.io/images/tiger.svg") +img <- magick::image_transparent(img, color = "white") +img2 <- magick::image_charcoal(img) +img2 <- magick::image_transparent(img2, color = "white") + +## ----message=FALSE------------------------------------------------------- +ggplot(data.frame(x=1:3, y=1:3), aes(x, y)) + + geom_point(size = 3) + + geom_abline(slope = 1, intercept = 0, linetype = 2, color = "blue") + + draw_image(img, x=1, y=1, scale = .9) + + draw_image(img2, x=2, y=2, scale = .9) + +## ----message=FALSE, fig.width=7, fig.height=2.5-------------------------- +p <- ggplot(iris, aes(x = Sepal.Length, fill = Species)) + geom_density(alpha = 0.7) +p2 <- ggdraw() + draw_image("http://jeroen.github.io/images/tiger.svg", scale = 0.9) +plot_grid(p, p2, labels = "AUTO") + diff --git a/inst/doc/introduction.Rmd b/inst/doc/introduction.Rmd index bed3049..ed6e647 100644 --- a/inst/doc/introduction.Rmd +++ b/inst/doc/introduction.Rmd @@ -200,7 +200,7 @@ ggdraw(plot.mpg) + 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 an inset plotted inside a larger graph. +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 an inset plotted inside a larger graph. ```{r message=FALSE, fig.width=7, fig.height=6} # plot.mpg and plot.diamonds were defined earlier library(viridis) @@ -211,3 +211,37 @@ ggdraw() + draw_plot_label(c("A", "B"), c(0, 0.5), c(1, 0.92), size = 15) ``` +We can also combine plots and images, using the function `draw_image()`. This function, which requires the **magick** package to be installed, can take images in many different formats and combine them with **ggplot2** plots. For example, we can use an image as a plot background: + + +```{r message=FALSE} +p <- ggplot(iris, aes(x=Sepal.Length, fill=Species)) + geom_density(alpha = 0.7) +ggdraw() + + draw_image("http://jeroen.github.io/images/tiger.svg") + + draw_plot(p) +``` + +Or we can manipulate images and draw them in plot coordinates: + +```{r message=FALSE, results="hide"} +img <- magick::image_read("http://jeroen.github.io/images/tiger.svg") +img <- magick::image_transparent(img, color = "white") +img2 <- magick::image_charcoal(img) +img2 <- magick::image_transparent(img2, color = "white") +``` + +```{r message=FALSE} +ggplot(data.frame(x=1:3, y=1:3), aes(x, y)) + + geom_point(size = 3) + + geom_abline(slope = 1, intercept = 0, linetype = 2, color = "blue") + + draw_image(img, x=1, y=1, scale = .9) + + draw_image(img2, x=2, y=2, scale = .9) +``` + +We can also make a plot grid with a regular plot and an image: + +```{r message=FALSE, fig.width=7, fig.height=2.5} +p <- ggplot(iris, aes(x = Sepal.Length, fill = Species)) + geom_density(alpha = 0.7) +p2 <- ggdraw() + draw_image("http://jeroen.github.io/images/tiger.svg", scale = 0.9) +plot_grid(p, p2, labels = "AUTO") +``` diff --git a/inst/doc/introduction.html b/inst/doc/introduction.html index 2d430bd..df23a6e 100644 --- a/inst/doc/introduction.html +++ b/inst/doc/introduction.html @@ -12,7 +12,7 @@ - + Introduction to cowplot @@ -70,7 +70,7 @@

Introduction to cowplot

Claus O. Wilke

-

2017-08-13

+

2017-10-20

@@ -97,6 +97,7 @@

Plot design

save_plot("mpg.png", plot.mpg, base_aspect_ratio = 1.3 # make room for figure legend ) +

The resulting figure:

By default, cowplot disables grid lines on the plot. In many cases, this is the cleanest and most elegant way to display the data. However, sometimes gridlines may be useful, and thus cowplot provides a simple way of adding gridlines, via the function background_grid():

@@ -121,15 +122,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")
-

+

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)
@@ -139,7 +140,8 @@ 

Arranging graphs into a grid

# each individual subplot should have an aspect ratio of 1.3 base_aspect_ratio = 1.3 )
-

The resulting figure:

+

+

The resulting figure:

The advantage of saving figures in this way is that you can first develop the code for individual figures, and once each individual figure looks the way you want it to you can easily combine the figures into a grid. save_plot() will make sure to scale the overall figure size such that the individual figures look the way they do when saved individually (as long as they all have the same base_aspect_ratio).

@@ -148,14 +150,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(
@@ -175,9 +177,9 @@ 

Generic plot annotations

colour = "gray60", fill = "gray80") + draw_label("Plot is underneath the grey boxes", x = 1, y = 1, vjust = 1, hjust = 1, size = 10, fontface = 'bold')
-

+

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 an inset plotted inside a larger graph.

+

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 an inset plotted inside a larger graph.

# plot.mpg and plot.diamonds were defined earlier
 library(viridis)
 ggdraw() +
@@ -185,7 +187,29 @@ 

Generic plot annotations

draw_plot(plot.mpg + scale_color_viridis(discrete = TRUE) + theme(legend.justification = "top"), 0.5, 0.52, 0.5, 0.4) + draw_plot_label(c("A", "B"), c(0, 0.5), c(1, 0.92), size = 15)
-

+

+

We can also combine plots and images, using the function draw_image(). This function, which requires the magick package to be installed, can take images in many different formats and combine them with ggplot2 plots. For example, we can use an image as a plot background:

+
p <- ggplot(iris, aes(x=Sepal.Length, fill=Species)) + geom_density(alpha = 0.7)
+ggdraw() +
+  draw_image("http://jeroen.github.io/images/tiger.svg") +
+  draw_plot(p)
+

+

Or we can manipulate images and draw them in plot coordinates:

+
img <- magick::image_read("http://jeroen.github.io/images/tiger.svg")
+img <- magick::image_transparent(img, color = "white")
+img2 <- magick::image_charcoal(img)
+img2 <- magick::image_transparent(img2, color = "white")
+
ggplot(data.frame(x=1:3, y=1:3), aes(x, y)) +
+  geom_point(size = 3) +
+  geom_abline(slope = 1, intercept = 0, linetype = 2, color = "blue") +
+  draw_image(img, x=1, y=1, scale = .9) +
+  draw_image(img2, x=2, y=2, scale = .9)
+

+

We can also make a plot grid with a regular plot and an image:

+
p <- ggplot(iris, aes(x = Sepal.Length, fill = Species)) + geom_density(alpha = 0.7)
+p2 <- ggdraw() + draw_image("http://jeroen.github.io/images/tiger.svg", scale = 0.9)
+plot_grid(p, p2, labels = "AUTO")
+

diff --git a/inst/doc/plot_annotations.html b/inst/doc/plot_annotations.html index 2c127ed..5bdd50f 100644 --- a/inst/doc/plot_annotations.html +++ b/inst/doc/plot_annotations.html @@ -12,7 +12,7 @@ - + Plot annotations @@ -70,7 +70,7 @@

Plot annotations

Claus O. Wilke

-

2017-08-13

+

2017-10-20

@@ -84,7 +84,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)
@@ -100,7 +100,7 @@

Joint plot titles

# 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 -

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.

+

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.

Annotations underneath plots

@@ -112,13 +112,13 @@

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.

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

+

This code also works with faceted plots:

plot.iris <- ggplot(iris, aes(Sepal.Length, Sepal.Width)) +
   geom_point() + facet_grid(. ~ Species) + stat_smooth(method = "lm") +
@@ -126,11 +126,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))
-

+

diff --git a/inst/doc/plot_grid.html b/inst/doc/plot_grid.html index f3c121f..6bf75ca 100644 --- a/inst/doc/plot_grid.html +++ b/inst/doc/plot_grid.html @@ -12,7 +12,7 @@ - + Arranging plots in a grid @@ -70,7 +70,7 @@

Arranging plots in a grid

Claus O. Wilke

-

2017-08-13

+

2017-10-20

@@ -84,17 +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')
-

+

For more complex combinations of plots that don’t have the same number of visual elements, alignment becomes more tricky. In those cases, you also have to specify the margin along which you want to align, via the axis option. For example, to align a faceted and a non-faceted plot such that the left axes are aligned, we can use the following:

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

Basic use of plot_grid()

panel_border() # and a border around each panel plot_grid(plot.iris, plot.mpg, labels = "AUTO", ncol = 1, align = 'v', axis = 'l') # aligning vertically along the left axis
-

+

Supported plot formats

@@ -127,32 +127,32 @@

Supported plot formats

Now we combine all these plots with plot_grid():

plot_grid(plot.mpg, recordedplot, plotfunc, gcircle, labels = "AUTO", hjust = 0, vjust = 1,
           scale = c(1., 1., 0.9, 0.9))
-

Note that the various alignment functions of plot_grid() only work with plots generated by ggplot, not with any of the other supported plot types.

+

Note that the various alignment functions of plot_grid() only work with plots generated by ggplot, not with any of the other supported plot types.

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)
-

+

You can also adjust the font family, font face, and color of the labels:

plot_grid(plot.mpg, plot.diamonds, labels = "AUTO", align = 'h', label_fontfamily = "serif",
           label_fontface = "plain", label_colour = "blue")
-

+

Labels can be moved via the label_x and label_y arguments, and justified via the hjust and vjust arguments. For example, to place labels into the bottom left corner, you can write:

plot_grid(plot.mpg, plot.diamonds, labels = "AUTO", align = 'h', label_size = 12,
           label_x = 0, label_y = 0, hjust = -0.5, vjust = -0.5 )
-

+

It is possible to adjust individual labels one by one by passing vectors of adjustment values to the options label_x, label_y, hjust, and vjust (example not shown).

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))
-

+

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. Also, we can’t auto-generate the labels in this case.) Alignment is a bit tricky in this case. However, it can be achieved using the align_plots() function. The trick is to first align the top-row plot (plot.iris) and the first botton-row plot (plot.mpg) vertically along the left axis, using the align_plots() function. Then these aligned plots can be passed to plot_grid(). Note that this vertical alignment does not interfere with the horizontal alignment of the bottom row.

# first align the top-row plot (plot.iris) with the left-most plot of the
 # bottom row (plot.mpg)
@@ -162,7 +162,7 @@ 

Nested plot grids

labels = c('B', 'C'), align = 'h', rel_widths = c(1, 1.3)) # then combine with the top row for final plot plot_grid(plots[[2]], bottom_row, labels = c('A', ''), ncol = 1, rel_heights = c(1, 1.2))
-

+

diff --git a/inst/doc/shared_legends.html b/inst/doc/shared_legends.html index 1f178a2..7e6a7f6 100644 --- a/inst/doc/shared_legends.html +++ b/inst/doc/shared_legends.html @@ -12,7 +12,7 @@ - + Shared legends @@ -70,7 +70,7 @@

Shared legends

Claus O. Wilke

-

2017-08-13

+

2017-10-20

@@ -98,7 +98,7 @@

2017-08-13

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
@@ -109,7 +109,7 @@ 

2017-08-13

# of one plot (via rel_widths). 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
@@ -120,7 +120,7 @@ 

2017-08-13

# of one plot (via rel_heights). 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"),
@@ -135,7 +135,7 @@ 

2017-08-13

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

+

One more example, now with a more complex plot arrangement:

# plot A
 p1 <- ggplot(iris, aes(Sepal.Length, Sepal.Width, color = Species)) + 
@@ -161,7 +161,7 @@ 

2017-08-13

# put together bottom row and then everything bottom_row <- plot_grid(plots[[2]], plots[[3]], legend, labels = c("B", "C"), rel_widths = c(1, 1, .3), nrow = 1) plot_grid(plots[[1]], bottom_row, labels = c("A"), ncol = 1)
-

+

diff --git a/vignettes/introduction.Rmd b/vignettes/introduction.Rmd index bed3049..ed6e647 100644 --- a/vignettes/introduction.Rmd +++ b/vignettes/introduction.Rmd @@ -200,7 +200,7 @@ ggdraw(plot.mpg) + 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 an inset plotted inside a larger graph. +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 an inset plotted inside a larger graph. ```{r message=FALSE, fig.width=7, fig.height=6} # plot.mpg and plot.diamonds were defined earlier library(viridis) @@ -211,3 +211,37 @@ ggdraw() + draw_plot_label(c("A", "B"), c(0, 0.5), c(1, 0.92), size = 15) ``` +We can also combine plots and images, using the function `draw_image()`. This function, which requires the **magick** package to be installed, can take images in many different formats and combine them with **ggplot2** plots. For example, we can use an image as a plot background: + + +```{r message=FALSE} +p <- ggplot(iris, aes(x=Sepal.Length, fill=Species)) + geom_density(alpha = 0.7) +ggdraw() + + draw_image("http://jeroen.github.io/images/tiger.svg") + + draw_plot(p) +``` + +Or we can manipulate images and draw them in plot coordinates: + +```{r message=FALSE, results="hide"} +img <- magick::image_read("http://jeroen.github.io/images/tiger.svg") +img <- magick::image_transparent(img, color = "white") +img2 <- magick::image_charcoal(img) +img2 <- magick::image_transparent(img2, color = "white") +``` + +```{r message=FALSE} +ggplot(data.frame(x=1:3, y=1:3), aes(x, y)) + + geom_point(size = 3) + + geom_abline(slope = 1, intercept = 0, linetype = 2, color = "blue") + + draw_image(img, x=1, y=1, scale = .9) + + draw_image(img2, x=2, y=2, scale = .9) +``` + +We can also make a plot grid with a regular plot and an image: + +```{r message=FALSE, fig.width=7, fig.height=2.5} +p <- ggplot(iris, aes(x = Sepal.Length, fill = Species)) + geom_density(alpha = 0.7) +p2 <- ggdraw() + draw_image("http://jeroen.github.io/images/tiger.svg", scale = 0.9) +plot_grid(p, p2, labels = "AUTO") +```