1--- 2title: "Aesthetic specifications" 3output: rmarkdown::html_vignette 4description: | 5 Customising how aesthetic specifications are represented on your plot. 6vignette: > 7 %\VignetteIndexEntry{Aesthetic specifications} 8 %\VignetteEngine{knitr::rmarkdown} 9 %\VignetteEncoding{UTF-8} 10--- 11 12```{r, include = FALSE} 13library(ggplot2) 14knitr::opts_chunk$set(fig.dpi = 96, collapse = TRUE, comment = "#>") 15``` 16 17This vignette summarises the various formats that grid drawing functions take. Most of this information is available scattered throughout the R documentation. This appendix brings it all together in one place. 18 19## Colour and fill 20 21Almost every geom has either colour, fill, or both. Colours and fills can be specified in the following ways: 22 23* A __name__, e.g., `"red"`. R has `r length(colours())` built-in named 24 colours, which can be listed with `colours()`. 25 26* An __rgb specification__, with a string of the form `"#RRGGBB"` where each of 27 the pairs `RR`, `GG`, `BB` consists of two hexadecimal digits giving a value 28 in the range `00` to `FF` 29 30 You can optionally make the colour transparent by using the form 31 `"#RRGGBBAA"`. 32 33* An __NA__, for a completely transparent colour. 34 35* The [munsell](https://github.com/cwickham/munsell) package, by Charlotte 36 Wickham, makes it easy to choose specific colours using a system designed by 37 Albert H. Munsell. If you invest a little in learning the system, it provides 38 a convenient way of specifying aesthetically pleasing colours. 39 40 ```{r} 41 munsell::mnsl("5PB 5/10") 42 ``` 43 44## Lines 45 46As well as `colour`, the appearance of a line is affected by `size`, `linetype`, `linejoin` and `lineend`. 47 48### Line type {#sec:line-type-spec} 49 50Line types can be specified with: 51 52* An __integer__ or __name__: 0 = blank, 1 = solid, 2 = dashed, 3 = dotted, 53 4 = dotdash, 5 = longdash, 6 = twodash, as shown below: 54 55 ```{r} 56 lty <- c("solid", "dashed", "dotted", "dotdash", "longdash", "twodash") 57 linetypes <- data.frame( 58 y = seq_along(lty), 59 lty = lty 60 ) 61 ggplot(linetypes, aes(0, y)) + 62 geom_segment(aes(xend = 5, yend = y, linetype = lty)) + 63 scale_linetype_identity() + 64 geom_text(aes(label = lty), hjust = 0, nudge_y = 0.2) + 65 scale_x_continuous(NULL, breaks = NULL) + 66 scale_y_reverse(NULL, breaks = NULL) 67 ``` 68 69* The lengths of on/off stretches of line. This is done with a string 70 containing 2, 4, 6, or 8 hexadecimal digits which give the lengths of 71 consecutive lengths. For example, the string `"33"` specifies three units 72 on followed by three off and `"3313"` specifies three units on followed by 73 three off followed by one on and finally three off. 74 75 ```{r} 76 lty <- c("11", "18", "1f", "81", "88", "8f", "f1", "f8", "ff") 77 linetypes <- data.frame( 78 y = seq_along(lty), 79 lty = lty 80 ) 81 ggplot(linetypes, aes(0, y)) + 82 geom_segment(aes(xend = 5, yend = y, linetype = lty)) + 83 scale_linetype_identity() + 84 geom_text(aes(label = lty), hjust = 0, nudge_y = 0.2) + 85 scale_x_continuous(NULL, breaks = NULL) + 86 scale_y_reverse(NULL, breaks = NULL) 87 ``` 88 89 The five standard dash-dot line types described above correspond to 44, 13, 90 1343, 73, and 2262. 91 92### Size 93 94The `size` of a line is its width in mm. 95 96### Line end/join paramters 97 98* The appearance of the line end is controlled by the `lineend` paramter, 99 and can be one of "round", "butt" (the default), or "square". 100 101 ```{r, out.width = "30%", fig.show = "hold"} 102 df <- data.frame(x = 1:3, y = c(4, 1, 9)) 103 base <- ggplot(df, aes(x, y)) + xlim(0.5, 3.5) + ylim(0, 10) 104 base + 105 geom_path(size = 10) + 106 geom_path(size = 1, colour = "red") 107 108 base + 109 geom_path(size = 10, lineend = "round") + 110 geom_path(size = 1, colour = "red") 111 112 base + 113 geom_path(size = 10, lineend = "square") + 114 geom_path(size = 1, colour = "red") 115 ``` 116 117* The appearance of line joins is controlled by `linejoin` and can be one of 118 "round" (the default), "mitre", or "bevel". 119 120 ```{r, out.width = "30%", fig.show = "hold"} 121 df <- data.frame(x = 1:3, y = c(9, 1, 9)) 122 base <- ggplot(df, aes(x, y)) + ylim(0, 10) 123 base + 124 geom_path(size = 10) + 125 geom_path(size = 1, colour = "red") 126 127 base + 128 geom_path(size = 10, linejoin = "mitre") + 129 geom_path(size = 1, colour = "red") 130 131 base + 132 geom_path(size = 10, linejoin = "bevel") + 133 geom_path(size = 1, colour = "red") 134 ``` 135 136Mitre joins are automatically converted to bevel joins whenever the angle is too small (which would create a very long bevel). This is controlled by the `linemitre` parameter which specifies the maximum ratio between the line width and the length of the mitre. 137 138## Polygons 139 140The border of the polygon is controlled by the `colour`, `linetype`, and `size` aesthetics as described above. The inside is controlled by `fill`. 141 142## Point 143 144### Shape {#sec:shape-spec} 145 146Shapes take five types of values: 147 148* An __integer__ in $[0, 25]$: 149 150 ```{r} 151 shapes <- data.frame( 152 shape = c(0:19, 22, 21, 24, 23, 20), 153 x = 0:24 %/% 5, 154 y = -(0:24 %% 5) 155 ) 156 ggplot(shapes, aes(x, y)) + 157 geom_point(aes(shape = shape), size = 5, fill = "red") + 158 geom_text(aes(label = shape), hjust = 0, nudge_x = 0.15) + 159 scale_shape_identity() + 160 expand_limits(x = 4.1) + 161 theme_void() 162 ``` 163 164* The __name__ of the shape: 165 166 ```{r out.width = "90%", fig.asp = 0.4, fig.width = 8} 167 shape_names <- c( 168 "circle", paste("circle", c("open", "filled", "cross", "plus", "small")), "bullet", 169 "square", paste("square", c("open", "filled", "cross", "plus", "triangle")), 170 "diamond", paste("diamond", c("open", "filled", "plus")), 171 "triangle", paste("triangle", c("open", "filled", "square")), 172 paste("triangle down", c("open", "filled")), 173 "plus", "cross", "asterisk" 174 ) 175 176 shapes <- data.frame( 177 shape_names = shape_names, 178 x = c(1:7, 1:6, 1:3, 5, 1:3, 6, 2:3, 1:3), 179 y = -rep(1:6, c(7, 6, 4, 4, 2, 3)) 180 ) 181 182 ggplot(shapes, aes(x, y)) + 183 geom_point(aes(shape = shape_names), fill = "red", size = 5) + 184 geom_text(aes(label = shape_names), nudge_y = -0.3, size = 3.5) + 185 scale_shape_identity() + 186 theme_void() 187 ``` 188 189* A __single character__, to use that character as a plotting symbol. 190 191* A `.` to draw the smallest rectangle that is visible, usualy 1 pixel. 192 193* An `NA`, to draw nothing. 194 195### Colour and fill 196 197Note that shapes 21-24 have both stroke `colour` and a `fill`. The size of the filled part is controlled by `size`, the size of the stroke is controlled by `stroke`. Each is measured in mm, and the total size of the point is the sum of the two. Note that the size is constant along the diagonal in the following figure. 198 199```{r} 200sizes <- expand.grid(size = (0:3) * 2, stroke = (0:3) * 2) 201ggplot(sizes, aes(size, stroke, size = size, stroke = stroke)) + 202 geom_abline(slope = -1, intercept = 6, colour = "white", size = 6) + 203 geom_point(shape = 21, fill = "red") + 204 scale_size_identity() 205``` 206 207## Text 208 209### Font face 210 211There are only three fonts that are guaranteed to work everywhere: "sans" (the default), "serif", or "mono": 212 213```{r} 214df <- data.frame(x = 1, y = 3:1, family = c("sans", "serif", "mono")) 215ggplot(df, aes(x, y)) + 216 geom_text(aes(label = family, family = family)) 217``` 218 219It's trickier to include a system font on a plot because text drawing is done differently by each graphics device (GD). There are five GDs in common use (`png()`, `pdf()`, on screen devices for Windows, Mac and Linux), so to have a font work everywhere you need to configure five devices in five different ways. Two packages simplify the quandary a bit: 220 221* `showtext` makes GD-independent plots by rendering all text as polygons. 222 223* `extrafont` converts fonts to a standard format that all devices can use. 224 225Both approaches have pros and cons, so you will to need to try both of them and see which works best for your needs. 226 227### Font face 228 229```{r} 230df <- data.frame(x = 1:4, fontface = c("plain", "bold", "italic", "bold.italic")) 231ggplot(df, aes(1, x)) + 232 geom_text(aes(label = fontface, fontface = fontface)) 233``` 234 235### Font size 236 237The `size` of text is measured in mm. This is unusual, but makes the size of text consistent with the size of lines and points. Typically you specify font size using points (or pt for short), where 1 pt = 0.35mm. ggplot2 provides this conversion factor in the variable `.pt`, so if you want to draw 12pt text, set `size = 12 / .pt`. 238 239### Justification 240 241Horizontal and vertical justification have the same parameterisation, either a string ("top", "middle", "bottom", "left", "center", "right") or a number between 0 and 1: 242 243* top = 1, middle = 0.5, bottom = 0 244* left = 0, center = 0.5, right = 1 245 246```{r} 247just <- expand.grid(hjust = c(0, 0.5, 1), vjust = c(0, 0.5, 1)) 248just$label <- paste0(just$hjust, ", ", just$vjust) 249 250ggplot(just, aes(hjust, vjust)) + 251 geom_point(colour = "grey70", size = 5) + 252 geom_text(aes(label = label, hjust = hjust, vjust = vjust)) 253``` 254 255Note that you can use numbers outside the range (0, 1), but it's not recommended. 256