```{r}
#| label: fig-histogram
#| fig-cap: "An embedded figure"
#| fig-alt: "A histogram of plant heights made with ggplot2"
#| message: false
#| warning: false
p <- ggplot(trait_height, aes(x = Value)) +
geom_histogram(boundary = 0) +
labs(x = "Height cm")
p # remember to print the plot
```
4 Figures, tables and equations
- learn how to add figures, tables, equations and formulae to your quarto document
4.1 Figures made in R
Plots can be included with a chunk that makes a figure with either base plot or ggplot.
If you make the plot with ggplot, remember to print it.
The label for the figure block must start with fig-
for the figure to get a figure number and be possible to link to. See Chapter 6 on cross-referencing.
4.1.1 Figure code block options
There are several useful block options for figures, including:
-
fig-cap
figure caption. -
fig-alt
alternate text to improve accessibility -
fig-height
figure height in inches (1 inch = 25.4 mm) -
fig-width
figure width in inches
The figure of height against treatment is missing a caption. Use code block options to give it an appropriate caption and alt-text.
Many journals require figures to be a specific size so they fit with the journal layout. For PLOSone, figures that fit in one column can be up to 13.2 cm (5.2 inches) wide. Use code block options to ensure that the figure would fit.
Sometimes it is useful to have R code in the chunk options.
We can do this by putting !expr
before the R code. For example, this chunk makes the figure caption include how many species there are in the dataset. It could be written with paste()
but I prefer glue::glue()
syntax - the code in the braces {}
is evaluated and included in the sentence.
```{r}
#| label: fig-r-in-chunk-options
#| fig-cap: !expr glue::glue("Heights of the {nrow(trait_height)} plants measured")
#| fig-alt: "A density plot of plant heights made with ggplot2"
#| message: false
#| warning: false
p <- ggplot(trait_height, aes(x = Value, fill = Treatment)) +
geom_density(bounds = c(0, Inf), alpha = 0.5) +
labs(x = "Plant height cm", y = "Density")
p
```
When you make a ggplot figure, you can specify the theme you want to use. For example, to use theme_classic()
, we could change the previous figure’s code to
p <- ggplot(trait_height, aes(x = Value, fill = Treatment)) +
geom_density(bounds = c(0, Inf), alpha = 0.5) +
labs(x = "Plant height cm", y = "Density") +
theme_classic()
p
To give all the figures in a document a consistent theme, you can set the default theme near the start of the document, perhaps in the code block where the package are loaded, with theme_set()
.
You can also set the default font size with the base_size
argument to theme_classic()
. Now we don’t need to add theme_classic()
to every figure. You can learn more about themes here.
4.2 Embedding external images
In the visual editor, photographs and other figures that have been prepared outside of R can be included with the insert tool by typing “/” on a blank line and choosing “Figure/Image”. This will open an menu to get the path to the image and set the caption etc. Once you close the menu, you can set the figure size. This will generate a bit of markdown that looks like.
![Marine diatoms](Pics/Marine_diatoms_SEM2.jpg){fig-alt="SEM photograph of marine diatoms" width="491"}
Alternatively, you can use knitr::include_graphics()
in a regular code block.
```{r}
#| label: fig-include-figure
#| out-width: "491px"
#| fig-cap: "An embedded figure of diatoms"
#| fig-alt: "An embedded figure of diatoms"
knitr::include_graphics("Pics/Marine_diatoms_SEM2.jpg")
```
Use the out-width
and out-height
chunk options to set the display size of the figure.
4.3 Tables
You can make tables in markdown by hand (the // insert tool helps a lot), but it often so much easier to use R.
Simple tables can be made with the function knitr::kable
. Several packages, including kableExtra
and gt
can make beautiful tables.
The block label need to start with tbl-
if the main caption and table number are to be shown.
4.3.1 kable
```{r}
#| label: tbl-kable
#| tbl-cap: Simple tables with `kable()`
trait_height_summary <- trait_height |>
group_by(Taxon) |>
summarise(mean = mean(Value), sd = sd(Value), n = n()) |>
filter(n > 10)
knitr::kable(trait_height_summary) # show first 5 rows
```
kable()
Taxon | mean | sd | n |
---|---|---|---|
bistorta vivipara | 3.749351 | 1.813518 | 77 |
carex rupestris | 3.713636 | 1.344228 | 22 |
cassiope tetragona | 8.093750 | 2.450978 | 16 |
dryas octopetala | 2.762222 | 1.540704 | 45 |
equisetum arvense | 4.068421 | 4.706184 | 38 |
equisetum scirpoides | 1.791667 | 1.454425 | 60 |
festuca rubra | 7.042105 | 2.094256 | 19 |
poa arctica | 7.867647 | 2.326360 | 34 |
salix polaris | 2.041667 | 1.102590 | 72 |
4.3.2 gt
The gt
package can make more elaborate tables than knitr::kable()
.
```{r}
#| label: tbl-gt
#| tbl-cap: Tables with `gt()`
#| tbl-subcap:
#| - "Basic `gt()` table"
#| - "`gt()` table with more features"
library(gt)
trait_height_summary |>
gt()
trait_height_summary|>
gt() |>
cols_label(mean = "Mean", # Display column headers
sd = "Standard deviation",
n = "Number") |>
fmt_number(columns = c(mean, sd)) |> # defaults to two decimal places
tab_spanner(label = "Height", columns = c(mean, sd))
```
gt()
Taxon | mean | sd | n |
---|---|---|---|
bistorta vivipara | 3.749351 | 1.813518 | 77 |
carex rupestris | 3.713636 | 1.344228 | 22 |
cassiope tetragona | 8.093750 | 2.450978 | 16 |
dryas octopetala | 2.762222 | 1.540704 | 45 |
equisetum arvense | 4.068421 | 4.706184 | 38 |
equisetum scirpoides | 1.791667 | 1.454425 | 60 |
festuca rubra | 7.042105 | 2.094256 | 19 |
poa arctica | 7.867647 | 2.326360 | 34 |
salix polaris | 2.041667 | 1.102590 | 72 |
Taxon | Height | Number | |
---|---|---|---|
Mean | Standard deviation | ||
bistorta vivipara | 3.75 | 1.81 | 77 |
carex rupestris | 3.71 | 1.34 | 22 |
cassiope tetragona | 8.09 | 2.45 | 16 |
dryas octopetala | 2.76 | 1.54 | 45 |
equisetum arvense | 4.07 | 4.71 | 38 |
equisetum scirpoides | 1.79 | 1.45 | 60 |
festuca rubra | 7.04 | 2.09 | 19 |
poa arctica | 7.87 | 2.33 | 34 |
salix polaris | 2.04 | 1.10 | 72 |
When reporting real numbers (i.e. numbers that have a decimal part), you need to decide how many digits to display. Be careful not to show spurious precision. You can use round()
to remove unwanted decimals, or gt::fmt_number()
to clean up one or more columns in a table.
Write a code block to make a table showing the mean leaf thickness and its standard deviation for each treatment.
Hint
sd()
for standard deviation
group_by()
and summarise()
then use any of the table making functions.
4.4 Equations
Equations are embedded in a pair of dollar symbols. RStudio will show a preview of the equation as you type it. Equations are written with LaTeX notation.
What | How | Output |
---|---|---|
Lower-case Greek letters | $\sigma$ |
\(\sigma\) |
Upper-Case Greek Letters | $\Sigma$ |
\(\Sigma\) |
Subscript | $\beta_{0}$ |
\(\beta_{0}\) |
Superscript | $\chi^{2}$ |
\(\chi^{2}\) |
Fractions | $\frac{1}{2}$ |
\(\frac{1}{2}\) |
Roots | $\sqrt{4} = 2$ |
\(\sqrt{4} = 2\) |
Here is an example of using an inline equation.
The $\delta^{13}C$ value ...
The \(\delta^{13}C\) value …
A double dollar enclosure gives the equation its own line. For example, this is the equation of a standard deviation that uses several different elements.
$$
SD = \sqrt{\frac{\sum_{i=1}^{n}{(x_i - \bar{x})^2}}{n-1}} $$
\[ SD = \sqrt{\frac{\sum_{i=1}^{n}{(x_i - \bar{x})^2}}{n-1}} \]
When making a complex formula, build one element at a time, often starting in the middle, rather than trying to get it all working at once.
4.5 Chemistry
Equations are printed in an italic font, which is not great for chemical formulae. We can fix this with the \mathrm
LaTeX command which forces roman typeface.
Sulphate $\mathrm{SO_4^{2-}}$
Sulphate \(\mathrm{SO_4^{2-}}\)
$$\mathrm{CO_3^{2-} + H^+ \rightleftharpoons HCO_3^{2-}}$$
\[\mathrm{CO_3^{2-} + H^+ \rightleftharpoons HCO_3^{2-}}\]