Visualising herbivory and climate change literature

ggplot2 is a hugely powerful R package whuch enables the creation of high quality scientific charting and visualisation for communication.

This note walks through some basics for creating charts to illustrate the literature review but there are lots of resources for chart creation of which this course really showcases what is possible.

Load libraries and import data

Code
## load libraries

library(pacman)
pacman::p_load(tidyverse, readxl, here, skimr, overviewR, ggmap, gt, gtsummary, DataExplorer)       ## readxl is needed to load excel files into R
                                              ## the `here` package helps with file paths


path <- here::here("data")

xls <- list.files(path, "xls", full.names = TRUE)

data <- readxl::read_xlsx(xls[2])
New names:
• `Deer (cervine)` -> `Deer (cervine)...10`
• `Livestock (not stated)` -> `Livestock (not stated)...11`
• `Simulated grazing` -> `Simulated grazing...13`
• `Deer (cervine)` -> `Deer (cervine)...35`
• `Simulated grazing` -> `Simulated grazing...41`
• `Livestock (not stated)` -> `Livestock (not stated)...42`
Code
introduce(data)
# A tibble: 1 × 9
   rows columns discrete_columns conti…¹ all_m…² total…³ compl…⁴ total…⁵ memor…⁶
  <int>   <int>            <int>   <int>   <int>   <int>   <int>   <int>   <dbl>
1    45      99               82       0      17    1815       0    4455  176360
# … with abbreviated variable names ¹​continuous_columns, ²​all_missing_columns,
#   ³​total_missing_values, ⁴​complete_rows, ⁵​total_observations, ⁶​memory_usage

Basic template for plotting categorical variables

Select categorical variables

Code
## Select categorical variables
chr_vars <- select_if(data, is.character) |> 
  janitor::clean_names()          ## this function converts variable names to snake case which makes them much more consistent

glimpse(chr_vars) 
Rows: 45
Columns: 82
$ item                                                  <chr> "Abdalla (2009) …
$ title                                                 <chr> "Application of …
$ wildlife_trusts_relevance                             <chr> "-Yes", "-Yes", …
$ evidence_point                                        <chr> "-Evidence point…
$ herbivore_species_or_simulation_exposure              <chr> "Cows (bovines)"…
$ horses_equines                                        <chr> NA, NA, NA, NA, …
$ cows_bovines                                          <chr> "-Breed not stat…
$ sheep_ovines                                          <chr> NA, NA, NA, NA, …
$ livestock_not_stated_11                               <chr> NA, NA, NA, NA, …
$ simulated_grazing_13                                  <chr> NA, NA, NA, NA, …
$ mixed_herd_or_single_species_exposure                 <chr> "-Single species…
$ climate_effect_outcome                                <chr> "-Nitrous oxide"…
$ soil_carbon                                           <chr> NA, NA, "-No cha…
$ digestive_methane_emissions_production_or_live_weight <chr> NA, NA, NA, "-No…
$ digestive_methane_emissions_land_area                 <chr> NA, NA, NA, "-In…
$ digestive_methane_emissions_per_animal                <chr> NA, NA, NA, NA, …
$ methane_flux_emissions                                <chr> NA, NA, NA, "-No…
$ nitrous_oxide                                         <chr> "-Unclear", "-Un…
$ co2_flux_emissions                                    <chr> NA, NA, NA, "-De…
$ above_ground_biomass                                  <chr> NA, NA, NA, "-De…
$ total_ghg_emissions_co2_equiv                         <chr> NA, NA, NA, "-In…
$ root_biomass                                          <chr> NA, NA, "-Increa…
$ direction_of_climate_change_outcome                   <chr> "-Unclear or mul…
$ herbivore_species_or_other_comparator                 <chr> "-Not applicable…
$ sheep_ovine                                           <chr> NA, NA, NA, NA, …
$ cows_bovine                                           <chr> NA, NA, NA, "-Ho…
$ mowing                                                <chr> NA, NA, "-Mowing…
$ cutting                                               <chr> NA, NA, NA, NA, …
$ no_herbivore_or_simulation                            <chr> NA, NA, NA, NA, …
$ not_applicable                                        <chr> "-Not applicable…
$ simulated_grazing_41                                  <chr> NA, NA, NA, NA, …
$ livestock_not_stated_42                               <chr> NA, NA, NA, NA, …
$ mixed_herd_or_single_species_comparator               <chr> "-Not applicable…
$ herbivore_density_frequency_exposure                  <chr> "-Medium density…
$ herbivore_density_frequency_comparator                <chr> "-Not applicable…
$ continent_and_country                                 <chr> "-Europe", "-Eur…
$ australia_and_oceania                                 <chr> NA, NA, NA, NA, …
$ europe                                                <chr> "-Ireland", "-Ir…
$ north_america                                         <chr> NA, NA, NA, NA, …
$ latitude_n_s                                          <chr> "-Latitude (stat…
$ longitude_e_w                                         <chr> "-Longitude (sta…
$ elevation                                             <chr> "-Elevation (sta…
$ site_name                                             <chr> "-Site name (ple…
$ study_characteristics                                 <chr> NA, NA, NA, "-St…
$ soil_type                                             <chr> "-Sandy\r\n-Loam…
$ current_land_use                                      <chr> "-Livestock graz…
$ previous_land_use                                     <chr> "-Livestock graz…
$ vegetation_type                                       <chr> "-Dominant veget…
$ habitat_management_exposure                           <chr> "-Fertiliser app…
$ habitat_management_comparator                         <chr> "-Not applicable…
$ herbivory_season_exposure                             <chr> "-Summer\r\n-Aut…
$ herbivory_season_comparator                           <chr> "-Not applicable…
$ effect_on_plants_or_soil_exposure                     <chr> "-Grazing", "-Gr…
$ effect_on_plants_or_soil_comparator                   <chr> "-Not applicable…
$ herbivore_management_exposure                         <chr> "-Farmed for foo…
$ herbivore_management_comparator                       <chr> "-Not applicable…
$ supplementary_feeding_or_treatment_exposure           <chr> "-Not applicable…
$ supplementary_feeding_or_teatment_comparator          <chr> "-Not applicable…
$ forage_species_exposure                               <chr> "-Not applicable…
$ forage_species_comparator                             <chr> "-Not applicable…
$ other_comparator_differences_please_add               <chr> "-Not applicable…
$ introduced_status_exposure                            <chr> "-Farmed_domesti…
$ introduced_status_comparator                          <chr> "-Not applicable…
$ conservation_status                                   <chr> "-Not protected"…
$ modifiers                                             <chr> NA, NA, NA, "-Pr…
$ soil_temperature                                      <chr> "-Not stated", "…
$ air_temperature                                       <chr> "-Air Temperatur…
$ precipitation                                         <chr> "-Precipitation …
$ growing_season                                        <chr> "-Not stated", "…
$ permafrost_or_snow                                    <chr> "-Neither presen…
$ disturbance_events                                    <chr> "-None mentioned…
$ predators                                             <chr> "-None mentioned…
$ other_herbivores                                      <chr> "-None mentioned…
$ habitat_productivity                                  <chr> "-Not stated", "…
$ biome                                                 <chr> "-Temperate", "-…
$ lowland_or_upland_300m_exposure                       <chr> "-Not available"…
$ habitat_exposure                                      <chr> "-Improved grass…
$ acidity_exposure                                      <chr> "-Neutral", "-Ne…
$ lowland_or_upland_300m_comparator                     <chr> "-Not available"…
$ habitat_comparator                                    <chr> "-Improved grass…
$ acidity_comparator                                    <chr> "-Neutral", "-Ne…
$ comments                                              <chr> "Herbivore Speci…

Labelling or modifying axes labels, adding titles

This is controlled by labs()

Code
g <- counts |>
  ggplot(aes(reorder(climate_effect_outcome, n), n)) +      
  geom_col(fill = "blue") +                             ## (fill = ... controls the colour of the bars)
  labs(y = "No of studies", 
       x = NULL, 
       title = "Climate outcomes") +
  coord_flip()  

g

Lets move the title to the left, and reduce the font size of the y axis labels, and we’ll change the scale of the x-axis

Positions of titles, axes labels, font sizes and so on are controlled by theme()

Code
g <- g +
  theme(plot.title.position = "plot", 
        axis.text.x = element_text(size = .5))

g

Further modifications

The value labels still need tidying but that may best be done in the data. We can change the colour of the bars and the background.

Code
g +
  theme(panel.background = element_blank())      ## removes panel background

Putting it all together

Code
chr_vars |>              
  count(climate_effect_outcome) |>
  ggplot(aes(reorder(climate_effect_outcome, n), n)) +     
  geom_col(fill = "blue") +
  labs(y = "No of studies", 
       x = NULL, 
       title = "Climate outcomes") +
  ylim(c(0, 14)) +
  coord_flip() +
  theme(plot.title.position = "plot", 
        axis.text.y = element_text(size = 7), 
        panel.background = element_blank())

Making it generic - writing a function

Now we have a basic template, it would be useful to reuse this for other variables.

To do this we can write a function - like a macro - which in R is very easy - just need to wrap our code in function() and identify the input we want to change - which in this case is other variables. Lets call the function plot_ordered_bar_chart. The core looks like this…

Code
plot_ordered_bar_chart <- function(df, var){
  df = df
  var <- enquo(var)
  df |> 
    count(!!var) |>
  ggplot(aes(reorder(!!var, n), n)) +     
  geom_col(fill = "blue") +
  labs(y = "No of studies", 
       x = NULL, 
       title = var) +
  ylim(c(0, 14)) +
  coord_flip() +
  theme(plot.title.position = "plot", 
        axis.text.y = element_text(size = 7), 
        panel.background = element_blank())
  
}



plot_ordered_bar_chart(chr_vars, var= climate_effect_outcome)

Code
variables <- colnames(chr_vars)

plot_ordered_bar_chart(chr_vars, horses_equines)

Small multiples

We might want to compare frequencies across multiple variables, for example

Code
## lets create a frequency table of the number of breeds mentioned in studes for each herbivore group

grouped <- data |>
  select(contains("vine")) |>
  pivot_longer(names_to = "herbivore", values_to = "breed", cols = 1:6) |>
  group_by(herbivore) |>
  count(breed)

grouped
# A tibble: 32 × 3
# Groups:   herbivore [6]
   herbivore      breed                             n
   <chr>          <chr>                         <int>
 1 Cows (bovine)  "-Aberdeen Angus"                 1
 2 Cows (bovine)  "-Aberdeen Angus X Limousin"      2
 3 Cows (bovine)  "-Breed not stated"               6
 4 Cows (bovine)  "-Charolais"                      1
 5 Cows (bovine)  "-Holstein Fresian"               8
 6 Cows (bovine)  "-Limousin X"                     4
 7 Cows (bovine)  "-Limousin X\r\n-Welsh Black"     1
 8 Cows (bovine)   <NA>                            22
 9 Cows (bovines) "-Aberdeen Angus"                 1
10 Cows (bovines) "-Belted Galloway"                1
# … with 22 more rows
# ℹ Use `print(n = ...)` to see more rows
Code
grouped |>
  drop_na() |>
  ggplot(aes(herbivore, n, fill = breed)) +
  geom_col(position = "fill") +
  scale_y_continuous(labels = scales::percent_format())

Code
#| label: faceted (small multiples)

grouped |>
  drop_na() |>
  ggplot(aes(reorder(breed, n), n)) +
  geom_col(position = "dodge") +
  coord_flip() +
  labs(x = "", 
       y = "No of studies") +
  #scale_y_continuous(labels = scales::percent_format()) +
  facet_wrap(~herbivore)