Learning Objectives

  • Learn some of the more commonly used R Markdown syntax.
  • Learn to generate formatted text and tables describing data and code.
  • Learn to embed formatted code, with additional arguments to exclude the code, output, or both from appearing in the rendered document.
  • Use R Markdown to create an annotated html document containing meta-data and exploratory data analysis of the CO2 dataset.

R Markdown

Log in to your Google Drive, and open your Environmental Data Analysis project. Click on the arrow next to the icon you would typically use to open a new R Script . Instead of choosing “R Script,” choose “R Markdown.” RStudio will ask you for a title and author name. You can also choose the type of document you wish to create. You can use R Markdown to create a Word, a pdf, or html document. The default is html, which is what we will create today.

Once you select these options, RStudio will open an R markdown template, which you can save as a plain text file with the extension .Rmd. The template will provide you with several sections of formatted text and code chunks to get you started.

You will notice that the file contains three kinds of content:

  • A header surrounded by ---. This header is optional, but it is good practice to keep a header that contains a title, author, and date of creation.
  • R code chunks that begin with ```{r} and close with ```. You can add additional arguments within {r} to specify whether this code should appear in your document, and whether the output of this code should appear in your document.
  • Text mixed with simple text formatting. For example, the ## before a line indicates that line should be formatted as a heading. You can also leave two spaces at the end of a line to indicate you wish to begin a new paragraph. If you are creating an html document, this part of the document also supports html code.

You can click “Knit” at anytime to generate your R Markdown document and ensure that your formatting is rendering properly. When you knit, RStudio will automatically save your .Rmd file.

Extensive resources are available for formatting in R Markdown.
Some of the basic syntax is available here: https://rmarkdown.rstudio.com/authoring_basics.html
You can also access information on R Markdown, including tutorials, from the creators at: https://rmarkdown.rstudio.com/
I have also provided you with an R Markdown cheat sheet on the Moodle page, which contains some of the more common formatting options.
When in doubt, I find that Googling “How do I _____ in R Markdown?” will usually return useful hints.

Today we will use the built-in CO2 data set to explore some of the options for annotating analysis of data and including meta-data and plots.

Challenge

Create a heading for “Packages” and an R chunk that loads all the packages we will use. Today we will use rmarkdown, knitr, and tidyverse. Add the argument warning = FALSE in {r} to hide any warnings related to the packages in the rendered document, e.g., ```{r, warning = FALSE}. Remember to use # within your code chunk to annotate what the next line of code is going to do.

Answer

## Packages

# Load rmarkdown package
library(rmarkdown)
# Load knitr package
library(knitr)
# Load tidyverse package
library(tidyverse)
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr     1.1.0     ✔ readr     2.1.4
## ✔ forcats   1.0.0     ✔ stringr   1.5.0
## ✔ ggplot2   3.4.1     ✔ tibble    3.1.8
## ✔ lubridate 1.9.2     ✔ tidyr     1.3.0
## ✔ purrr     1.0.1     
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag()    masks stats::lag()
## ℹ Use the ]8;;http://conflicted.r-lib.org/conflicted package]8;; to force all conflicts to become errors

Challenge

Create a heading for “Data” and briefly describe the CO2 dataset we are using. Include a code chunk that loads the data, inspects the structure of the dataframe, and summarizes the dataframe. Remember to use # in your code chunk to annotate what the next line of code is going to do.
Hint: You can run ?CO2 in the console to retrieve a help file that contains meta-data on the CO2 dataset.

Answer

## The CO2 dataset

The CO2 dataset contains responses in CO2 uptake rates to increasing CO2 for grass species Echinochloa crus-galli, collected from populations in Quebec and Mississippi. Half of the plants were exposed to cold conditions the night before measurements, and half were kept at ambient temperatures.

# Load the CO2 data set
data(CO2)
# Inspect the CO2 data frame
str(CO2)
## Classes 'nfnGroupedData', 'nfGroupedData', 'groupedData' and 'data.frame':   84 obs. of  5 variables:
##  $ Plant    : Ord.factor w/ 12 levels "Qn1"<"Qn2"<"Qn3"<..: 1 1 1 1 1 1 1 2 2 2 ...
##  $ Type     : Factor w/ 2 levels "Quebec","Mississippi": 1 1 1 1 1 1 1 1 1 1 ...
##  $ Treatment: Factor w/ 2 levels "nonchilled","chilled": 1 1 1 1 1 1 1 1 1 1 ...
##  $ conc     : num  95 175 250 350 500 675 1000 95 175 250 ...
##  $ uptake   : num  16 30.4 34.8 37.2 35.3 39.2 39.7 13.6 27.3 37.1 ...
##  - attr(*, "formula")=Class 'formula'  language uptake ~ conc | Plant
##   .. ..- attr(*, ".Environment")=<environment: R_EmptyEnv> 
##  - attr(*, "outer")=Class 'formula'  language ~Treatment * Type
##   .. ..- attr(*, ".Environment")=<environment: R_EmptyEnv> 
##  - attr(*, "labels")=List of 2
##   ..$ x: chr "Ambient carbon dioxide concentration"
##   ..$ y: chr "CO2 uptake rate"
##  - attr(*, "units")=List of 2
##   ..$ x: chr "(uL/L)"
##   ..$ y: chr "(umol/m^2 s)"
# Summarize CO2 data
summary(CO2)
##      Plant             Type         Treatment       conc          uptake     
##  Qn1    : 7   Quebec     :42   nonchilled:42   Min.   :  95   Min.   : 7.70  
##  Qn2    : 7   Mississippi:42   chilled   :42   1st Qu.: 175   1st Qu.:17.90  
##  Qn3    : 7                                    Median : 350   Median :28.30  
##  Qc1    : 7                                    Mean   : 435   Mean   :27.21  
##  Qc3    : 7                                    3rd Qu.: 675   3rd Qu.:37.12  
##  Qc2    : 7                                    Max.   :1000   Max.   :45.50  
##  (Other):42

Creating a data dictionary

It is good practice to include meta-data where you store your data. Meta-data can be as simple as a plain text file containing information on data collection methods, the variables included in your data frame, and any other information a user may find helpful. If your data have been published in a journal article or an online database, you can also provide a suggested citation.

R Markdown documents are commonly included with manuscript submissions to document the process used to clean, manipulate, analyze, and plot data. You can also provide meta-data for the data frame in the form of a data dictionary. For an example, you can view a meta-data file I created in R Markdown for a recent journal article here.

We will use two approaches to include a data dictionary in an R Markdown document: in-line tables and “kables.”

In-line tables

First we will create a table by typing information directly into the R Markdown document.

The code to create a table is as follows:
Table Header | Second Header
------------- | -------------
Table Cell | Cell 2
Cell 3 | Cell 4

So I could use the following code to create a table for the first couple rows of meta-data by typing the following as simple text:

Variable | Description
-------- | ------------
Plant | an ordered factor with levels Qn1 < Qn2 ... < Mc1 giving a unique identifier for each plant
Type | a factor with levels Quebec Mississippi giving the origin of the plant

Variable Description
Plant an ordered factor with levels Qn1 < Qn2 … < Mc1 giving a unique identifier for each plant
Type a factor with levels Quebec Mississippi giving the origin of the plant

Note that this approach will only work if you leave a blank line containing two spaces before the first line of your table.

Generating tables using kable()

The other approach is to create a data frame or .csv file containing your meta-data, and create a table using the kable() function. This approach is much more efficient for tables larger than ~2-3 rows.

To create a data frame from scratch in R, I will create a vector for each column using c() and then combine them into a data frame using data.frame(). This is relatively easy to do, as I can copy and paste the information from the help file.

# Create vector of variable names
Variable <- c("Plant", "Type", "Treatment", "conc", "uptake")
# Create vector of descriptions
Description <- c("an ordered factor with levels Qn1 < Qn2 <...< Mc1 giving a unique identifier for each plant",
                 "a factor with levels Quebec Mississippi giving the origin of the plant",
                 "a factor with levels nonchilled chilled",
                 "a numeric vector of ambient carbon dioxide concentrations (mL/L)",
                 "a numeric vector of carbon dioxide uptake rates (umol/m^2 sec)")
#Create data frame from two column vectors
metadata <- data.frame(Variable, Description)

Once I have a data frame metadata, I can use the kable() function in a code chunk to create a table.

# Create table from metadata data frame
kable(metadata)
Variable Description
Plant an ordered factor with levels Qn1 < Qn2 <…< Mc1 giving a unique identifier for each plant
Type a factor with levels Quebec Mississippi giving the origin of the plant
Treatment a factor with levels nonchilled chilled
conc a numeric vector of ambient carbon dioxide concentrations (mL/L)
uptake a numeric vector of carbon dioxide uptake rates (umol/m^2 sec)

If I already had a .csv file containing the meta-data, I could import the file from my working directory, save it as an object, and then use the kable() function to create a table from that object. Again, I would do this within a code chunk.

# Import metadata from .csv file
metadata2 <- read.csv("metadata.csv")
# Create table
kable(metadata2)
Variable Description
Plant an ordered factor with levels Qn1 < Qn2 <…< Mc1 giving a unique identifier for each plant
Type a factor with levels Quebec Mississippi giving the origin of the plant
Treatment a factor with levels nonchilled chilled
conc a numeric vector of ambient carbon dioxide concentrations (mL/L)
uptake a numeric vector of carbon dioxide uptake rates (umol/m^2 sec)

Note that if you wanted the table, but did not want the code used to generate the table to appear in your R Markdown document, you can add the argument echo = FALSE in {r}, e.g., ```{r, echo = F}.

Challenge

Using either the in-line table or kable approach, generate a table that includes the name of each variable in the CO2 data frame and a brief desciption of each variable.

Inserting Images

You can insert images into an R Markdown document by including a link to an image file in your working directory, or by creating a link to a permanent web location. Including a link to a web location is often risky, as image locations can change or be replaced (story there). You can also create an image caption in association with the image.

For example, if I wanted to insert an image for this assignment, I would save the image file to my project folder and type the following code as simple text in my R Markdown document:
![**Fig. 1** *Echinochloa crus-galli*, the grass species used in experiments in Potvin et al. (1990). Source: Wikimedia commons.](E-crus-galli.jpg)

The code is in the format ![Caption](imagename.jpg). Note that I have added modifiers to create bold ** and italicized * fonts in the caption.

Fig. 1 Echinochloa crus-galli, the grass species used in experiments in Potvin et al. (1990). Source: Wikimedia commons.

Challenge

Find a photo of Echinochloa crus-galli using a Google image search.
You want to make sure you find a photo that is available for reuse.
Under the search bar, click Tools then click Usage Rights and Creative Commons licenses.
Choose an image. Right click, choose Save image as... and save the image to your project folder.
Insert the image in R Markdown, with a caption describing the image and the name of the image file with correct file extension.

In-line equations

At times, you may wish to include a formatted equation in a document. For example, in the power analysis workshop, I embedded formatted equations explaining how “effect size” was calculated for various statistical tests. Here, I may wish to include an equation that explains the anticipated relationship between CO2 and CO2 uptake. I can format equations in R Markdown either inline or as a separate line.
For a thorough treatment of mathematical notation in R Markdown, see https://rpruim.github.io/s341/S19/from-class/MathinRmd.html.

Example: $v = V_{max}\frac{[CO_{2}]}{[CO_{2}]_{k}+[CO_{2}]}$ is rendered as \(v = V_{max}\frac{[CO_{2}]}{[CO_{2}]_{k}+[CO_{2}]}\)

Example: $$v = V_{max}\frac{[CO_{2}]}{[CO_{2}]_{k}+[CO_{2}]}$$ is rendered as \[v = V_{max}\frac{[CO_{2}]}{[CO_{2}]_{k}+[CO_{2}]}\]

This equation describes a saturating relationship between CO2 uptake and the amount of CO2 available, where:
\(v\) = CO2 uptake rate
\(V_{max}\) = maximum uptake rate
\([CO_2]_{k}\) = half-saturation concentration

Challenge

Create a new section in your R Markdown document titled “Hypotheses.”
In text, briefly explain why you may expect uptake to follow a hyperbolic, or saturating, relationship. (Hint: Google “Michaelis-Menten kinetics”)
Following the example above, create an equation describing this relationship. Be sure to define your terms.
Below the equation, insert an image showing Michaelis-Menten relationship. (Use the method you used to insert the plant photo.)

Including Plots

You can also embed plots. For example, I may want to create a scatterplot examining the relationship between ambient CO2 and CO2 uptake for only those plants collected from Mississippi and chilled prior to measurement. I will first create a new object that includes only those data.
In the next unit, we will learn to make plots using the package ggplot2. For now, use the function qplot() in the ggplot2 package to generate a plot using similar syntax to the base plots you have already made.

# Create dataframe of chilled plants from Mississippi
MS_chilled <- CO2[CO2$Type == "Mississippi" & CO2$Treatment == "chilled",]
# Plot relationship for replicate plants
qplot(x = conc,
      y = uptake,
      data = MS_chilled,
      facets = ~Plant,
      geom = "line",
      xlab = "CO2 Concentration (ppm)",
      ylab = "CO2 Uptake Rate (umol/m^2/s)")

Note that you can add the echo = FALSE parameter to the code chunk to prevent printing of the R code that generated the plot, e.g., ```{r, echo = FALSE}.

Challenge

Create a new section titled “Results.”
In this section, create two plots: One for plants collected in Mississippi (using the code provided above) and one for plants collected in Quebec (which you will need to create using the code above as a model). For both, include only plants that were chilled prior to measurement.
Below each plot, include a figure caption that describes the plot content. (You can type this text directly into the R Markdown document below the code chunk that generates the plot. If the text appears next to the plot, you can insert a blank line with two spaces to make your caption begin on a new line.)