Chapter 12 Answers to practical exercises

Below are all the questions and answers to the practical exercises at the end of each chapter.

Note that you will need to make sure R knows where to find your data. My data are all in a data folder within the R Project I’m working with. Assuming you have not moved the data from where you downloaded everything, you will have a separate R Project and data folder for each of the chapters of this online book.

12.1 Need to know R

No exercises

12.2 Data wrangling

Using the frog-eyes-raw-data.csv data and R, create a new dataframe that contains only the columns genus_species, Family, and two new columns containing the species mean values for rootmass and eyemean. Note that we will talk more about this dataset in later exercises, but it comes from K. N. Thomas et al. (2020).

There are many ways of doing this, but here’s how I would do this:

# Load packages
library(tidyverse)
# Read in the data
frog <- read_csv("data/frog-eyes-raw-data.csv")
# Take a look at it
glimpse(frog)
## Rows: 640
## Columns: 21
## $ genus_species    <chr> "Acris_gryllus", "Acris_gryllus", "Acris_gryllus", "Adenomus_kelaar…
## $ Order            <chr> "Anura", "Anura", "Anura", "Anura", "Anura", "Anura", "Anura", "Anu…
## $ Family           <chr> "Hylidae", "Hylidae", "Hylidae", "Bufonidae", "Bufonidae", "Hyperol…
## $ Genus            <chr> "Acris", "Acris", "Acris", "Adenomus", "Adenomus", "Afrixalus", "Af…
## $ Species          <chr> "gryllus", "gryllus", "gryllus", "kelaartii", "kelaartii", "dorsali…
## $ tiplabel         <chr> "Acris_gryllus_Hylidae", "Acris_gryllus_Hylidae", "Acris_gryllus_Hy…
## $ SVL_mm           <dbl> 22.6, 20.7, 16.7, 41.0, 41.7, 25.8, 24.7, 25.4, 48.9, 49.1, 62.5, 6…
## $ Mass_g           <dbl> 1.1, 0.9, 0.6, 6.2, 6.5, 1.5, 1.3, 1.3, 7.0, 7.0, 14.0, 12.0, 30.1,…
## $ rootmass         <dbl> 1.0322801, 0.9654894, 0.8434327, 1.8370906, 1.8662556, 1.1447142, 1…
## $ ED_right_mm      <dbl> 3.3, 3.1, 2.9, NA, 4.7, 3.7, 3.6, 3.5, 7.4, 6.3, 8.3, 7.7, 8.7, 8.1…
## $ ED_left_mm       <dbl> 2.3, 2.8, 2.5, 4.6, 4.7, 3.8, 3.5, 3.8, 7.2, 6.8, 7.8, 7.5, 8.3, 8.…
## $ eyemean          <dbl> 2.80, 2.95, 2.70, 4.60, 4.70, 3.75, 3.55, 3.65, 7.30, 6.55, 8.05, 7…
## $ CD_right_mm      <dbl> 3.1, 2.3, 2.0, NA, 3.8, 2.9, 2.8, 2.7, 5.7, 4.8, 5.8, 5.3, 6.7, 7.3…
## $ CD_left_mm       <dbl> 2.5, 2.2, 2.3, 3.9, 4.2, 3.0, 2.7, 2.8, 5.3, 5.2, 5.9, 5.3, 6.6, 7.…
## $ cormean          <dbl> 2.80, 2.25, 2.15, 3.90, 4.00, 2.95, 2.75, 2.75, 5.50, 5.00, 5.85, 5…
## $ Adult_habitat    <chr> "Ground-dwelling", "Ground-dwelling", "Ground-dwelling", "Subfossor…
## $ Activity_period  <chr> "Both", "Both", "Both", "Nocturnal", "Nocturnal", "Nocturnal", "Noc…
## $ Mating_habitat   <chr> "Lentic water", "Lentic water", "Lentic water", "Lotic water", "Lot…
## $ Life_history     <chr> "Free-living larvae", "Free-living larvae", "Free-living larvae", "…
## $ Larval_habitat   <chr> "Lentic water", "Lentic water", "Lentic water", NA, NA, "Lentic wat…
## $ Sex_dichromatism <chr> "Absent", "Absent", "Absent", "Absent", "Absent", "Absent", "Absent…
# Create a new dataframe called frog2
frog2 <-
  # Start with the frog dataframe
  frog %>%
  # Select only the columns of interest
  dplyr::select(genus_species, Family, rootmass, eyemean) %>%
  # Group by species name, and Family (or summarise will try and average this too!)
  group_by(genus_species, Family) %>%
  # Summarise to get the mean values
  summarise(mean_rootmass = mean(rootmass),
            mean_eyemean = mean(eyemean))
# Look at frog2
glimpse(frog2)
## Rows: 220
## Columns: 4
## Groups: genus_species [220]
## $ genus_species <chr> "Acris_gryllus", "Adenomus_kelaartii", "Afrixalus_dorsalis", "Agalychn…
## $ Family        <chr> "Hylidae", "Bufonidae", "Hyperoliidae", "Hylidae", "Phyllomedusidae", …
## $ mean_rootmass <dbl> 0.9470674, 1.8516731, 1.1091667, 2.1313583, 2.7840487, 1.9917795, 1.25…
## $ mean_eyemean  <dbl> 2.816667, 4.650000, 3.650000, 7.375000, 8.700000, 6.166667, 4.116667, …
# Write to file
# This is commented out as I don't want to save this
# write_csv(frog2, path = "data/clean-frog-data.csv")

12.3 Phylogenies

Read in the frog-tree.nex phylogeny from the folder. This comes from Feng et al. (2017). Then do the following:

Read the tree into R.

# Load packages
library(ape)
library(ggtree)
library(tidyverse)

# Read in the tree
frogtree <- read.nexus("data/frog-tree.nex")

# Look at it
frogtree
## 
## Phylogenetic tree with 214 tips and 213 internal nodes.
## 
## Tip labels:
##   Ascaphus_truei_Ascaphidae, Leiopelma_hochstetteri_Leiopelmatidae, Alytes_obstetricans_Alytidae, Discoglossus_pictus_Alytidae, Barbourula_busuangensis_Bombinatoridae, Bombina_orientalis_Bombinatoridae, ...
## 
## Rooted; includes branch lengths.
  1. Use R functions to determine:
  1. how many species are in the tree?
# Look at the tree structure
str(frogtree)
# Or the whole tree
frogtree

There are 214 tips

  1. is the tree fully resolved?
# Check whether the tree is binary/fully resolved
is.binary(frogtree)

Yes

  1. is the tree rooted?
# Check whether the tree is rooted
is.rooted(frogtree)

Yes

  1. Use plot.phylo to plot the tree.
    1. Can you change the size of the tip labels?
    2. Can you make a fan-shaped plot?
    3. Can you change the colour of the tips and branches?
# Plot the tree
plot(frogtree, 
     no.margin = TRUE, # to make sure it fills the whole space
     type = "fan", # to make a fan tree
     cex = 0.6, # to reduce the tip label size (default = 1)
     tip.color = "deeppink", # to change the tip colour
     edge.color = "springgreen") # to change the branch colour
# yuk!
  1. Save the tree to file as “mysuperdoopertree.nex”
# Save the tree
write.nexus(frogtree, file = "data/mysuperdoopertree.nex")

12.4 Preparation

In the data folder there is another tree (primate-tree.nex) and dataset (primate-data.csv) for investigating the evolution of primate life-history variables. These data come from the PanTHERIA database (Jones et al. 2009) and 10kTrees (Arnold, Matthews, and Nunn 2010).

Read in the tree and data then prepare them for a PCM analysis.

# Load packages
library(ape)
library(geiger)
library(tidyverse)
library(phytools)

# Read in the tree
primatetree <- read.nexus("data/primate-tree.nex")
# Look at the tree summary
str(primatetree)
## List of 4
##  $ edge       : int [1:446, 1:2] 227 228 229 230 231 232 233 234 234 235 ...
##  $ edge.length: num [1:446] 4.95 17.69 19.65 8.12 4.82 ...
##  $ Nnode      : int 221
##  $ tip.label  : chr [1:226] "Allenopithecus_nigroviridis" "Cercopithecus_ascanius" "Cercopithecus_cephus" "Cercopithecus_cephus_cephus" ...
##  - attr(*, "class")= chr "phylo"
##  - attr(*, "order")= chr "cladewise"
# Plot the tree as a circular/fan phylogeny with small labels
plot(primatetree, cex = 0.2, typ = "fan", no.margin = TRUE)

# Check whether the tree is binary
# We want this to be TRUE
is.binary(primatetree) 
## [1] FALSE
# It is FALSE so make the tree binary:
primatetree <- multi2di(primatetree)

# Check whether the tree is binary now...
is.binary(primatetree) 
## [1] TRUE
# Check whether the tree is rooted
# We want this to be TRUE
is.rooted(primatetree)
## [1] TRUE
# Check whether the tree is ultrametric
# We want this to be TRUE, but it is FALSE
is.ultrametric(primatetree)
## [1] FALSE
# Force ultrametric
primatetree <- force.ultrametric(primatetree)
## ***************************************************************
## *                          Note:                              *
## *    force.ultrametric does not include a formal method to    *
## *    ultrametricize a tree & should only be used to coerce    *
## *   a phylogeny that fails is.ultramtric due to rounding --   *
## *    not as a substitute for formal rate-smoothing methods.   *
## ***************************************************************
# Read in the data
primatedata <- read_csv("data/primate-data.csv")
## Rows: 77 Columns: 9
## ── Column specification ──────────────────────────────────────────────────────────────────────
## Delimiter: ","
## chr (3): Order, Family, Binomial
## dbl (6): AdultBodyMass_g, GestationLen_d, HomeRange_km2, MaxLongevity_m, SocialGroupSize, ...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
# Look at the data
glimpse(primatedata)
## Rows: 77
## Columns: 9
## $ Order           <chr> "Primates", "Primates", "Primates", "Primates", "Primates", "Primate…
## $ Family          <chr> "Atelidae", "Atelidae", "Atelidae", "Pitheciidae", "Cebidae", "Cebid…
## $ Binomial        <chr> "Ateles belzebuth", "Ateles geoffroyi", "Ateles paniscus", "Calliceb…
## $ AdultBodyMass_g <dbl> 6692.42, 7582.40, 8697.25, 958.13, 558.00, 290.21, 123.94, 7077.66, …
## $ GestationLen_d  <dbl> 138.20, 226.37, 228.18, 164.00, 153.99, 144.00, 134.44, 174.43, 148.…
## $ HomeRange_km2   <dbl> 2.28000, 0.73000, 1.36000, 0.02000, 0.32000, 0.02000, 0.00212, 0.510…
## $ MaxLongevity_m  <dbl> 336.0, 327.6, 453.6, 303.6, 214.8, 201.6, 181.2, 252.0, 339.6, 276.0…
## $ SocialGroupSize <dbl> 14.50, 42.00, 20.00, 2.95, 6.85, 8.55, 6.00, 20.35, 26.30, 11.00, 16…
## $ SocialStatus    <dbl> 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1,…
# Replace spaces with underscores in species names
primatedata <- 
  primatedata %>%
  mutate(Binomial = str_replace(string = Binomial, pattern = " ", replacement = "_"))
# Check it worked
glimpse(primatedata)
## Rows: 77
## Columns: 9
## $ Order           <chr> "Primates", "Primates", "Primates", "Primates", "Primates", "Primate…
## $ Family          <chr> "Atelidae", "Atelidae", "Atelidae", "Pitheciidae", "Cebidae", "Cebid…
## $ Binomial        <chr> "Ateles_belzebuth", "Ateles_geoffroyi", "Ateles_paniscus", "Calliceb…
## $ AdultBodyMass_g <dbl> 6692.42, 7582.40, 8697.25, 958.13, 558.00, 290.21, 123.94, 7077.66, …
## $ GestationLen_d  <dbl> 138.20, 226.37, 228.18, 164.00, 153.99, 144.00, 134.44, 174.43, 148.…
## $ HomeRange_km2   <dbl> 2.28000, 0.73000, 1.36000, 0.02000, 0.32000, 0.02000, 0.00212, 0.510…
## $ MaxLongevity_m  <dbl> 336.0, 327.6, 453.6, 303.6, 214.8, 201.6, 181.2, 252.0, 339.6, 276.0…
## $ SocialGroupSize <dbl> 14.50, 42.00, 20.00, 2.95, 6.85, 8.55, 6.00, 20.35, 26.30, 11.00, 16…
## $ SocialStatus    <dbl> 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1,…
# Check whether the names match in the data and the tree
check <- name.check(phy = primatetree, data = primatedata, 
                    data.names = primatedata$Binomial)
# Look at check
check
## $tree_not_data
##   [1] "Allenopithecus_nigroviridis"                  
##   [2] "Allocebus_trichotis"                          
##   [3] "Alouatta_caraya"                              
##   [4] "Alouatta_sara"                                
##   [5] "Aotus_azarae"                                 
##   [6] "Aotus_azarae_infulatus"                       
##   [7] "Aotus_lemurinus_griseimembra"                 
##   [8] "Aotus_nancymaae"                              
##   [9] "Arctocebus_aureus"                            
##  [10] "Arctocebus_calabarensis"                      
##  [11] "Ateles_fusciceps"                             
##  [12] "Ateles_geoffroyi_ornatus"                     
##  [13] "Ateles_geoffroyi_vellerosus"                  
##  [14] "Avahi_laniger"                                
##  [15] "Avahi_occidentalis"                           
##  [16] "Brachyteles_arachnoides"                      
##  [17] "Bunopithecus_hoolock"                         
##  [18] "Callicebus_donacophilus"                      
##  [19] "Callithrix_(Mico)_emiliae"                    
##  [20] "Callithrix_argentata"                         
##  [21] "Callithrix_aurita"                            
##  [22] "Callithrix_geoffroyi"                         
##  [23] "Callithrix_humeralifera"                      
##  [24] "Callithrix_kuhli"                             
##  [25] "Callithrix_penicillata"                       
##  [26] "Cercocebus_agilis"                            
##  [27] "Cercocebus_atys"                              
##  [28] "Cercocebus_torquatus"                         
##  [29] "Cercopithecus_cephus_cephus"                  
##  [30] "Cercopithecus_cephus_ngottoensis"             
##  [31] "Cercopithecus_diana"                          
##  [32] "Cercopithecus_erythrogaster_erythrogaster"    
##  [33] "Cercopithecus_erythrotis"                     
##  [34] "Cercopithecus_hamlyni"                        
##  [35] "Cercopithecus_lhoesti"                        
##  [36] "Cercopithecus_lowei"                          
##  [37] "Cercopithecus_mona"                           
##  [38] "Cercopithecus_petaurista"                     
##  [39] "Cercopithecus_preussi"                        
##  [40] "Cercopithecus_solatus"                        
##  [41] "Cercopithecus_wolfi"                          
##  [42] "Cheirogaleus_crossleyi"                       
##  [43] "Chlorocebus_aethiops"                         
##  [44] "Chlorocebus_pygerythrus"                      
##  [45] "Chlorocebus_sabaeus"                          
##  [46] "Chlorocebus_tantalus"                         
##  [47] "Colobus_angolensis"                           
##  [48] "Eulemur_albifrons"                            
##  [49] "Eulemur_albocollaris"                         
##  [50] "Eulemur_collaris"                             
##  [51] "Eulemur_macaco_flavifrons"                    
##  [52] "Eulemur_macaco_macaco"                        
##  [53] "Eulemur_rubriventer"                          
##  [54] "Eulemur_rufus"                                
##  [55] "Eulemur_sanfordi"                             
##  [56] "Euoticus_elegantulus"                         
##  [57] "Galago_gallarum"                              
##  [58] "Galago_zanzibaricus"                          
##  [59] "Gorilla_gorilla_gorilla"                      
##  [60] "Hapalemur_alaotrensis"                        
##  [61] "Hapalemur_aureus"                             
##  [62] "Hapalemur_griseus_griseus"                    
##  [63] "Hapalemur_griseus_meridionalis"               
##  [64] "Hapalemur_occidentalis"                       
##  [65] "Homo_sapiens"                                 
##  [66] "Hylobates_agilis"                             
##  [67] "Hylobates_klossii"                            
##  [68] "Hylobates_moloch"                             
##  [69] "Hylobates_muelleri"                           
##  [70] "Indri_indri"                                  
##  [71] "Leontopithecus_chrysomelas"                   
##  [72] "Leontopithecus_chrysopygus"                   
##  [73] "Lepilemur_aeeclis"                            
##  [74] "Lepilemur_ankaranensis"                       
##  [75] "Lepilemur_dorsalis"                           
##  [76] "Lepilemur_edwardsi"                           
##  [77] "Lepilemur_microdon"                           
##  [78] "Lepilemur_mitsinjoensis"                      
##  [79] "Lepilemur_randrianasoli"                      
##  [80] "Lepilemur_ruficaudatus"                       
##  [81] "Lepilemur_sahamalazensis"                     
##  [82] "Lepilemur_seali"                              
##  [83] "Lepilemur_septentrionalis"                    
##  [84] "Lophocebus_aterrimus"                         
##  [85] "Loris_lydekkerianus_grandis"                  
##  [86] "Loris_lydekkerianus_malabaricus"              
##  [87] "Macaca_arctoides"                             
##  [88] "Macaca_assamensis"                            
##  [89] "Macaca_cyclopis"                              
##  [90] "Macaca_hecki"                                 
##  [91] "Macaca_leonina"                               
##  [92] "Macaca_maura"                                 
##  [93] "Macaca_nigra"                                 
##  [94] "Macaca_nigrescens"                            
##  [95] "Macaca_ochreata"                              
##  [96] "Macaca_ochreata_brunnescens"                  
##  [97] "Macaca_pagensis"                              
##  [98] "Macaca_siberu"                                
##  [99] "Macaca_thibetana"                             
## [100] "Macaca_tonkeana"                              
## [101] "Mandrillus_leucophaeus"                       
## [102] "Microcebus_berthae"                           
## [103] "Microcebus_bongolavensis"                     
## [104] "Microcebus_danfossi"                          
## [105] "Microcebus_griseorufus"                       
## [106] "Microcebus_jollyae"                           
## [107] "Microcebus_lehilahytsara"                     
## [108] "Microcebus_lokobensis"                        
## [109] "Microcebus_mittermeieri"                      
## [110] "Microcebus_myoxinus"                          
## [111] "Microcebus_ravelobensis"                      
## [112] "Microcebus_sambiranensis"                     
## [113] "Microcebus_simmonsi"                          
## [114] "Microcebus_tavaratra"                         
## [115] "Nomascus_gabriellae"                          
## [116] "Nomascus_leucogenys"                          
## [117] "Nycticebus_coucang"                           
## [118] "Nycticebus_pygmaeus"                          
## [119] "Pan_troglodytes_schweinfurthii"               
## [120] "Pan_troglodytes_troglodytes"                  
## [121] "Pan_troglodytes_verus"                        
## [122] "Papio_papio"                                  
## [123] "Piliocolobus_badius"                          
## [124] "Pongo_abelii"                                 
## [125] "Pongo_pygmaeus_pygmaeus"                      
## [126] "Presbytis_melalophos"                         
## [127] "Propithecus_coquereli"                        
## [128] "Propithecus_diadema"                          
## [129] "Propithecus_edwardsi"                         
## [130] "Propithecus_tattersalli"                      
## [131] "Pygathrix_nemaeus"                            
## [132] "Rhinopithecus_avunculus"                      
## [133] "Rhinopithecus_bieti"                          
## [134] "Rhinopithecus_brelichi"                       
## [135] "Rhinopithecus_roxellana"                      
## [136] "Rungwecebus_kipunji"                          
## [137] "Saguinus_geoffroyi"                           
## [138] "Saguinus_imperator"                           
## [139] "Saimiri_boliviensis_boliviensis"              
## [140] "Saimiri_oerstedii"                            
## [141] "Trachypithecus_(Trachypithecus)_auratus"      
## [142] "Trachypithecus_(Trachypithecus)_poliocephalus"
## [143] "Trachypithecus_cristatus"                     
## [144] "Trachypithecus_francoisi"                     
## [145] "Trachypithecus_johnii"                        
## [146] "Trachypithecus_phayrei"                       
## [147] "Trachypithecus_pileatus"                      
## [148] "Varecia_rubra"                                
## [149] "Varecia_variegata_variegata"                  
## 
## $data_not_tree
## character(0)
# 149 species are in the tree but not the data
# 0 species are in the data but not the tree
  
# Remove species missing from the data
mytree <- drop.tip(primatetree, check$tree_not_data)

# Remove species missing from the tree
matches <- match(primatedata$Binomial, check$data_not_tree, nomatch = 0)
mydata <- subset(primatedata, matches == 0)

# Look at the tree summary
str(mytree)
## List of 4
##  $ edge       : int [1:152, 1:2] 78 79 80 81 82 83 84 85 86 87 ...
##  $ edge.length: num [1:152] 4.95 17.69 19.65 8.12 4.82 ...
##  $ Nnode      : int 76
##  $ tip.label  : chr [1:77] "Cercopithecus_ascanius" "Cercopithecus_cephus" "Cercopithecus_mitis" "Cercopithecus_neglectus" ...
##  - attr(*, "class")= chr "phylo"
##  - attr(*, "order")= chr "cladewise"
##  - attr(*, "RSS")= num 2.08e-08
# Look at the data
glimpse(mydata)
## Rows: 77
## Columns: 9
## $ Order           <chr> "Primates", "Primates", "Primates", "Primates", "Primates", "Primate…
## $ Family          <chr> "Atelidae", "Atelidae", "Atelidae", "Pitheciidae", "Cebidae", "Cebid…
## $ Binomial        <chr> "Ateles_belzebuth", "Ateles_geoffroyi", "Ateles_paniscus", "Calliceb…
## $ AdultBodyMass_g <dbl> 6692.42, 7582.40, 8697.25, 958.13, 558.00, 290.21, 123.94, 7077.66, …
## $ GestationLen_d  <dbl> 138.20, 226.37, 228.18, 164.00, 153.99, 144.00, 134.44, 174.43, 148.…
## $ HomeRange_km2   <dbl> 2.28000, 0.73000, 1.36000, 0.02000, 0.32000, 0.02000, 0.00212, 0.510…
## $ MaxLongevity_m  <dbl> 336.0, 327.6, 453.6, 303.6, 214.8, 201.6, 181.2, 252.0, 339.6, 276.0…
## $ SocialGroupSize <dbl> 14.50, 42.00, 20.00, 2.95, 6.85, 8.55, 6.00, 20.35, 26.30, 11.00, 16…
## $ SocialStatus    <dbl> 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1,…
# Convert to a dataframe
mydata <- as.data.frame(mydata)
# Check this is now a data frame
class(mydata)
## [1] "data.frame"
## OPTIONAL
# Write the cleaned data to a new file
# write_csv(mydata, path = "data/clean-primate-data.csv")

# Write the cleaned tree to a new file
# write.nexus(mytree, file = "data/clean-primate-tree.nex")

12.5 Phylogenetic signal

In the data folder there is another tree (primate-tree.nex) and dataset (primate-data.csv) for investigating the evolution of primate life-history variables. These data come from the PanTHERIA database (Jones et al. 2009) and 10kTrees (Arnold, Matthews, and Nunn 2010).

Read in the tree and data, then prepare them for a PCM analysis (you may have already done this in the previous exercise which should save you some time). Then answer the following questions:

# Load the packages
library(ape)
library(geiger)
library(caper)
library(tidyverse)
library(phytools)

### Prepare the tree and the data as shown in the Preparation answer above ###
### This should mean you now have mydata and mytree ready to work with ###
  1. What is \(\lambda\) for log gestation length?
# First create logGestation containing just log gestation length values
logGestation <- log(pull(mydata, GestationLen_d))
# Give log Eye names = species names at the tips of the phylogeny
names(logGestation) <- mydata$Binomial
# Look at the first few rows
head(logGestation)
##   Ateles_belzebuth   Ateles_geoffroyi    Ateles_paniscus  Callicebus_moloch 
##           4.928702           5.422171           5.430135           5.099866 
##  Callimico_goeldii Callithrix_jacchus 
##           5.036888           4.969813
# Estimate lambda
lambdaGestation <- phylosig(mytree, logGestation, method = "lambda", test = TRUE)
# Look at the results
lambdaGestation
## 
## Phylogenetic signal lambda : 0.948326 
## logL(lambda) : 34.9204 
## LR(lambda=0) : 89.026 
## P-value (based on LR test) : 3.89649e-21

0.948

  1. What is K for log gestation length?
# Estimate Blomberg’s *K*
KGestation <- phylosig(mytree, logGestation, method = "K", test = TRUE, nsim = 1000)
# Look at the results
KGestation
## 
## Phylogenetic signal K : 0.775777 
## P-value (based on 1000 randomizations) : 0.001

0.776

  1. What is D for social status?
# Prepare the data for use in caper
primate <- comparative.data(phy = mytree, data = mydata, 
                            names.col = Binomial, vcv = TRUE, 
                            na.omit = FALSE, warn.dropped = TRUE)

# Force the phylogeny to have polytomies again nrather than zero length branches
primate$phy <- di2multi(primate$phy)

# Estimate D
Dsocial <- phylo.d(data = primate, names.col = tiplabel, binvar = SocialStatus, 
                  permut = 1000)

# Look at the output
Dsocial

About -0.70. This is a randomisation test so may vary slightly

12.6 PGLS

In the data folder there is another tree (primate-tree.nex) and dataset (primate-data.csv) for investigating the evolution of primate life-history variables. These data come from the PanTHERIA database (Jones et al. 2009) and 10kTrees (Arnold, Matthews, and Nunn 2010).

Let’s investigate the relationship between gestation length in Primates and their body size. Theory leads us to believe that bigger mammals have longer gestation lengths (compare mice to elephants), but is this true in Primates?

Read in the tree and data, then prepare them for a PCM analysis (you may have already done this in a previous exercise which should save you some time). Fit a PGLS model to investigate the relationship between log gestation length (y = log(GestationLen_d)) and log body size (x = log(AdultBodyMass_g)) in Primates. Don’t forget to look at the model diagnostics!

# Load the packages
library(ape)
library(geiger)
library(caper)
library(tidyverse)

### Prepare the tree and the data as shown in the Preparation answer above ###
### This should mean you now have mydata and mytree ready to work with ###

# Prepare the data for use in caper
primate <- comparative.data(phy = mytree, data = mydata, 
                            names.col = Binomial, vcv = TRUE, 
                            na.omit = FALSE, warn.dropped = TRUE)

# Check the list of dropped species is what you expected
primate$dropped$tips
primate$dropped$unmatched.rows

# Fit a PGLS model
model.pgls <- pgls(log(GestationLen_d) ~ log(AdultBodyMass_g), 
                   data = primate, lambda = "ML", bounds = list(lambda = c(0.01, 1)))

### Model diagnostics
# Make a plotting window with 4 panes as there are four plots
par(mfrow = c(2, 2))
# Now plot the model diagnostics
plot(model.pgls)
# Return the plot window to one pane for later plotting
par(mfrow = c(1, 1))

# Look at the model outputs
summary(model.pgls)

# Plot the results
ggplot(mydata, aes(x = log(AdultBodyMass_g), 
                     y = log(GestationLen_d))) +
  geom_point() +
  geom_abline(slope = coefficients(model.pgls)[2], 
              intercept = coefficients(model.pgls)[1]) +
  theme_bw()

Then answer the following questions.

  1. What is the maximum likelihood estimate of \(\lambda\) in the model?
# Look at the model outputs. Lambda is near the middle
summary(model.pgls)

0.892

  1. What are the confidence intervals on the maximum likelihood estimate of \(\lambda\). How would you interpret these?
# Extract the confidence intervals on lambda
pgls.confint(model.pgls, "lambda")$ci.val

0.753434, 0.966543. We are 95% certain that \(\lambda\) is between these two values.

  1. Plot the \(\lambda\) profile for the the maximum likelihood estimate of \(\lambda\). What does it look like?
# Create a likelihood profile of the lambda estimate
lambda.profile <- pgls.profile(model.pgls, "lambda")
# Plot the likelihood profile
plot(lambda.profile)
  1. Is there a significant relationship between log gestation length and log body size? What is the slope of this relationship?
# Look at the model outputs. 
summary(model.pgls)

Yes. p < 0.001. Slope = 0.105 \(\pm\) 0.019

12.7 MCMCglmm

In the data folder there is another tree (primate-tree.nex) and dataset (primate-data.csv) for investigating the evolution of primate life-history variables. These data come from the PanTHERIA database (Jones et al. 2009) and 10kTrees (Arnold, Matthews, and Nunn 2010).

Let’s repeat the analyses we did in the PGLS chapter but using MCMCglmm. We will investigate the relationship between gestation length in Primates and their body size.

Read in the tree and data, then prepare them for a PCM analysis (you may have already done this in a previous exercise which should save you some time). Fit a MCMCglmm model to investigate the relationship between log gestation length (y = log(GestationLen_d)) and log body size (x = log(AdultBodyMass_g)) in Primates. Don’t forget to check that the model has converged, and to look at the model diagnostics and for autocorrelation.

# Load the packages
library(tidyverse)
library(ape)
library(geiger)
library(MCMCglmm)
library(coda)

## MCMCglmm specific preparation

# Remove zero length branches and replace with polytomies
mytree2 <- di2multi(mytree)

# Remove node labels 
mytree2$node.label <- NULL

# Get the inverse vcv matrix for the phylogeny
inv.phylo <- inverseA(mytree2, nodes = "TIPS", scale = TRUE)$Ainv

# Set up priors for MCMCglmm
# Inverse Wishart with V = 1 and nu = 0.02
# i.e. fairly uninformative priors
prior <- list(G = list(G1 = list(V = 1, nu = 0.02)),
              R = list(V = 1, nu = 0.02))

# Set number of iterations
nitt <- 1000000

# Set burnin
burnin <- 1000

# Sampling interval
thin <- 500

# Fit MCMCglmm model
model_mcmcglmm <- MCMCglmm(log(GestationLen_d) ~ log(AdultBodyMass_g), 
                           data = mydata, 
                           random = ~ Binomial,
                           ginverse = list(Binomial = inv.phylo), 
                           prior = prior,
                           nitt = nitt, thin = thin, burnin = burnin,
                           verbose = TRUE)

# Save the model
# saveRDS(model_mcmcglmm, file = "data/model_mcmcglmm_primate.rda")
# Read in the saved model output run in advance to save time
model_mcmcglmm <- readRDS("data/model_mcmcglmm_primate.rda")

## Did the model converge?
# Plot model diagnostics for MCMCglmm
# For fixed effects
plot(model_mcmcglmm$Sol)  

# Plot model diagnostics for MCMCglmm
# For random effects
plot(model_mcmcglmm$VCV)  

# Calculate ESS
effectiveSize(model_mcmcglmm$Sol[, 1:model_mcmcglmm$Fixed$nfl, 
                                 drop = FALSE])[[1]]
## [1] 1998
# Look for autocorrelation
autocorr(model_mcmcglmm$VCV)
## , , Binomial
## 
##                Binomial        units
## Lag 0      1.0000000000 -0.301495441
## Lag 500    0.0008200833 -0.004268382
## Lag 2500   0.0052744916  0.038062203
## Lag 5000  -0.0446744855  0.014890222
## Lag 25000  0.0104991347 -0.008261472
## 
## , , units
## 
##               Binomial        units
## Lag 0     -0.301495441  1.000000000
## Lag 500    0.012393397  0.002583728
## Lag 2500   0.001343481 -0.015740264
## Lag 5000   0.039810907 -0.009084549
## Lag 25000  0.029927932 -0.018984469
  1. What is \(\lambda\) in the model?
# Get lambda
lambda <- model_mcmcglmm$VCV[,'Binomial']/
          (model_mcmcglmm$VCV[,'Binomial'] + model_mcmcglmm$VCV[,'units'])

# Posterior mean of lambda
mean(lambda)
## [1] 0.8699022
# Posterior mode of lambda
posterior.mode(lambda)
##      var1 
## 0.8925655

Posterior mean lambda is 0.870, the posterior mode is 0.893

  1. What are the 95% credible intervals (HPD) around \(\lambda\)?
# HPD interval
HPDinterval(lambda)
##          lower     upper
## var1 0.7615502 0.9613453
## attr(,"Probability")
## [1] 0.9499499

HPD interval of lambda is 0.762 to 0.961

  1. Plot the \(\lambda\) profile for the the maximum likelihood estimate of \(\lambda\).
# Plot the posterior for lambda
ggplot(as.data.frame(lambda), aes(x = lambda))+
  geom_density() +
  geom_vline(xintercept = posterior.mode(lambda), colour = "red") +
  geom_vline(xintercept = HPDinterval(lambda)[[1]], 
             linetype = "dotted", colour = "red") +
  geom_vline(xintercept = HPDinterval(lambda)[[2]], 
             linetype = "dotted", colour = "red") +
  theme_bw()
## Don't know how to automatically pick scale for object of type <mcmc>. Defaulting to
## continuous.

  1. Is there a relationship between log gestation length and log body size? What is the slope of this relationship?
## Results
# Look at summary of fixed effect results
summary(model_mcmcglmm)$solutions
##                      post.mean   l-95% CI  u-95% CI eff.samp        pMCMC
## (Intercept)          4.2876174 3.97118491 4.6374322     1998 0.0005005005
## log(AdultBodyMass_g) 0.1050013 0.06455035 0.1460903     1998 0.0005005005
# Look at G-structure and R-structure posterior modes
posterior.mode(model_mcmcglmm$VCV)
##    Binomial       units 
## 0.040772793 0.005794703
# Look at G-structure and R-structure 95% credible intervals
HPDinterval(model_mcmcglmm$VCV)
##                lower      upper
## Binomial 0.021550421 0.06927166
## units    0.002813069 0.01043645
## attr(,"Probability")
## [1] 0.9499499

Yes! The slope is 0.105 (0.065-0.146). This is close to what we got using PGLS.

12.8 Models of evolution with continuous traits

In the data folder there is another tree (primate-tree.nex) and dataset (primate-data.csv) for investigating the evolution of primate life-history variables. These data come from the PanTHERIA database (Jones et al. 2009) and 10kTrees (Arnold, Matthews, and Nunn 2010).

Read in the tree and data, then prepare them for a PCM analysis (you may have already done this in a previous exercise which should save you some time). Fit Brownian and OU models to log adult body mass for Primates (AdultBodyMass_g). Then answer the following questions.

# Load the packages
library(ape)
library(geiger)
library(caper)
library(tidyverse)

### Prepare the tree and the data as shown in the Preparation answer above ###
### This should mean you now have mydata and mytree ready to work with ###

# Reorder the data so the tree and data are in the same order
mydata <- mydata[match(mytree$tip.label, mydata$Binomial), ]

# Create logBodyMass containing just log body mass values
logBodyMass <- log(pull(mydata, AdultBodyMass_g))
# Give log body mass names = species names at the tips of the phylogeny
names(logBodyMass) <- mydata$Binomial
# Look at the first few rows
head(logBodyMass)
##  Cercopithecus_ascanius    Cercopithecus_cephus     Cercopithecus_mitis 
##                8.171950                8.144644                8.525417 
## Cercopithecus_neglectus Cercopithecus_nictitans      Erythrocebus_patas 
##                8.580078                8.567299                8.982975
# Fit the Brownian model
BM <- fitContinuous(mytree, logBodyMass, model = c("BM"))
# Fit the OU model
OU <- fitContinuous(mytree, logBodyMass, model = c("OU"))
  1. Which model fits best?
# Could look at AIC weights...
aic.scores <- setNames(c(BM$opt$aic, OU$opt$aic), c("BM","OU"))
aicw(aic.scores)
##         fit delta         w
## BM 160.1921     0 0.7310586
## OU 162.1921     2 0.2689414
# Or just the raw AIC values
BM$opt$aic
## [1] 160.1921
OU$opt$aic
## [1] 162.1921

BM but only by a small amount

  1. What is the rate of evolution for the Brownian model?
# Look at the whole output
BM
## GEIGER-fitted comparative model of continuous data
##  fitted 'BM' model parameters:
##  sigsq = 0.028655
##  z0 = 6.773956
## 
##  model summary:
##  log-likelihood = -78.096042
##  AIC = 160.192084
##  AICc = 160.354246
##  free parameters = 2
## 
## Convergence diagnostics:
##  optimization iterations = 100
##  failed iterations = 0
##  number of iterations with same best fit = 100
##  frequency of best fit = 1.00
## 
##  object summary:
##  'lik' -- likelihood function
##  'bnd' -- bounds for likelihood search
##  'res' -- optimization iteration summary
##  'opt' -- maximum likelihood parameter estimates
# Or just the one parameter
BM$opt$sigsq
## [1] 0.0286548

0.028655

  1. What is the strength of pull towards the long-term mean in the OU model? What does this value suggest?
# Look at the whole output
OU
## GEIGER-fitted comparative model of continuous data
##  fitted 'OU' model parameters:
##  alpha = 0.000000
##  sigsq = 0.028655
##  z0 = 6.773956
## 
##  model summary:
##  log-likelihood = -78.096042
##  AIC = 162.192084
##  AICc = 162.520851
##  free parameters = 3
## 
## Convergence diagnostics:
##  optimization iterations = 100
##  failed iterations = 0
##  number of iterations with same best fit = 50
##  frequency of best fit = 0.50
## 
##  object summary:
##  'lik' -- likelihood function
##  'bnd' -- bounds for likelihood search
##  'res' -- optimization iteration summary
##  'opt' -- maximum likelihood parameter estimates
# Or just the one parameter
OU$opt$alpha
## [1] 2.571618e-42

<0.0001, i.e. very close to zero which makes it very close to a Brownian model

12.9 Models of evolution with discrete traits

In the data folder there is another tree (primate-tree.nex) and dataset (primate-data.csv) for investigating the evolution of primate life-history variables. These data come from the PanTHERIA database (Jones et al. 2009) and 10kTrees (Arnold, Matthews, and Nunn 2010).

Read in the tree and data, then prepare them for a PCM analysis (you may have already done this in a previous exercise which should save you some time). Fit equal rates, symmetric rates and all rates different models to the social status variable for Primates (SocialStatus). Note that social status has two states: non-social (1) or social (2).

# Load the packages
library(ape)
library(geiger)
library(caper)
library(tidyverse)
library(phytools)

### Prepare the tree and the data as shown in the Preparation answer above ###
### This should mean you now have mydata and mytree ready to work with ###

# Reorder the data so the tree and data are in the same order
mydata <- mydata[match(mytree$tip.label, mydata$Binomial), ]

# Create Social containing just social status values
Social <- pull(mydata, SocialStatus)
# Give social status names = species names at the tips of the phylogeny
names(Social) <- mydata$Binomial
# Look at the first few rows
head(Social)
##  Cercopithecus_ascanius    Cercopithecus_cephus     Cercopithecus_mitis 
##                       2                       2                       2 
## Cercopithecus_neglectus Cercopithecus_nictitans      Erythrocebus_patas 
##                       2                       2                       2
# Fit the ER model
equal <- fitDiscrete(mytree, Social, model = "ER")
# Fit the ARD model
ard <- fitDiscrete(mytree, Social, model = "ARD")

Then answer the following questions.

  1. Which model fits best?
# Using AIC weights
aic.scores <- setNames(c(equal$opt$aic, ard$opt$aic), 
                       c("equal", "different"))
aicw(aic.scores)
##                fit    delta          w
## equal     38.98307 5.313651 0.06556956
## different 33.66942 0.000000 0.93443044
# Or just the raw AIC values
equal$opt$aic
## [1] 38.98307
ard$opt$aic
## [1] 33.66942

All rates different

  1. What is the transition rate from non-social (1) to social (2), and vice versa, in the all rates different model? What does this mean biologically?
# Could look at the model output
ard
## GEIGER-fitted comparative model of discrete data
##  fitted Q matrix:
##                   1             2
##     1 -9.264914e-03  9.264914e-03
##     2  1.476682e-17 -1.476682e-17
## 
##  model summary:
##  log-likelihood = -14.834711
##  AIC = 33.669423
##  AICc = 33.831585
##  free parameters = 2
## 
## Convergence diagnostics:
##  optimization iterations = 100
##  failed iterations = 0
##  number of iterations with same best fit = 46
##  frequency of best fit = 0.46
## 
##  object summary:
##  'lik' -- likelihood function
##  'bnd' -- bounds for likelihood search
##  'res' -- optimization iteration summary
##  'opt' -- maximum likelihood parameter estimates
# Or plot the Q matrix as network
plot.gfit(ard)

1 to 2 is ~0.009, 2 to 1 is very close to zero. Transitions from social (2) to non-social (1) behaviour are extremely rare.

  1. Plot ancestral state estimates of social status (from the ARD model) on the phylogeny. Is the root node estimated as being non-social or social?
# Ancestral state estimation (ignore the warnings)
ancestral_social <- ace(Social, mytree, type = "discrete", model = "ARD")
## Warning in sqrt(diag(solve(h))): NaNs produced
# Choose colours
social_colours <- c("deeppink", "goldenrod")

# Plot the tree with colours at the tips and nodes to represent socail status
plot(mytree, cex = 0.5, adj = c(0.2), type = "fan", 
     no.margin = TRUE, show.tip.label = TRUE)
tiplabels(pch = 16, col = social_colours[mydata$SocialStatus])
nodelabels(pie = ancestral_social$lik.anc, piecol = social_colours, cex = 0.5)
legend("bottomleft", pch = 15, bty = "n",
       legend = c("Non Social", "Social"), 
       col = social_colours)

Root is non-social

  1. Why didn’t I ask you to fit the symmetric model?

Because with only two states the symmetric model is equivalent to the equal rates model

12.10 Beyond simple macroevolutionary models of trait evolution

In the data folder there is another tree (primate-tree.nex) and dataset (primate-data.csv) for investigating the evolution of primate life-history variables. These data come from the PanTHERIA database (Jones et al. 2009) and 10kTrees (Arnold, Matthews, and Nunn 2010).

Read in the tree and data, then prepare them for a PCM analysis (you may have already done this in a previous exercise which should save you some time).

Using log body size (AdultBodyMass_g) as your continuous trait, and social status (SocialStatus) to define the selective regimes, fit (A) a multi-rate Brownian motion model and (B) an OU model with trait optima or long-term mean values for different evolutionary regimes but the same \(\sigma^2\) and \(\alpha\). Note that social status has two states: non-social (1) or social (2). Assume it is evolving according to an all rates different model.

# Load the packages
library(ape)
library(geiger)
library(caper)
library(tidyverse)
library(OUwie)

### Prepare the tree and the data as shown in the Preparation answer above ###
### This should mean you now have mydata and mytree ready to work with ###

# Reorder the data so the tree and data are in the same order
mydata <- mydata[match(mytree$tip.label, mydata$Binomial), ]

# Create Social containing just social status values
Social <- pull(mydata, SocialStatus)
# Give social status names = species names at the tips of the phylogeny
names(Social) <- mydata$Binomial

# Simulate node and tip values for 500 trees using the ARD model
trees.ARD <- make.simmap(mytree, Social, model = "ARD", nsim = 500)
## make.simmap is sampling character histories conditioned on
## the transition matrix
## 
## Q =
##              1           2
## 1 -0.009264911 0.009264911
## 2  0.000000000 0.000000000
## (estimated using likelihood);
## and (mean) root node prior probabilities
## pi =
##   1   2 
## 0.5 0.5
# Store the results of the summary of the 500 trees
summary.ARD <- summary(trees.ARD)

# Get the max likelihood state at each node
best <- apply(summary.ARD$ace[1:76, ], 1, which.max)

# Assign regimes to the tree node labels
mytree$node.label <- levels(as.factor(mydata$SocialStatus))[best]

# Make new dataset with just three columns for OUwie
bodymass <- data.frame(species = mydata$Binomial, 
                    regime = mydata$SocialStatus, 
                    trait = log(mydata$AdultBodyMass_g))

# Fit BMS model
BMS <- OUwie(mytree, bodymass, model = "BMS", root.station = FALSE)
## Warning: An algorithm was not specified. Defaulting to computing the determinant and
## inversion of the vcv.
## Initializing... 
## Finished. Begin thorough search... 
## Finished. Summarizing results.
# Fit OUM model
OUM <- OUwie(mytree, bodymass, model = "OUM")
## Warning: An algorithm was not specified. Defaulting to computing the determinant and
## inversion of the vcv.
## Initializing... 
## Finished. Begin thorough search... 
## Finished. Summarizing results.

Then answer the following questions:

  1. Which is the best fitting model?
# Extract AICc scores from the models
aic.scores <- setNames(c(BMS$AICc, OUM$AICc), 
                           c("BMS", "OUM"))
# Get aic weights
aicw(aic.scores)

OUM

  1. If you were running these analyses for a publication, what additional models would you compare these models to?

BM and single peak OU for sure. Possibly one or more of the more complex models if you had a good biological reason to

  1. In the multi rate Brownian model, which social status state has the higher rate of log body mass evolution?
# Look at the model output
BMS

Non-social (1) has the higher rate of body mass evolution 0.04031313

  1. Look at the parameter estimates of the multi peak OU model. Do you see anything worrying there? It might help to look at a histogram showing the body sizes of species in the non-social and the social categories.
# Look at the output
OUM

# Plot the body sizes for the different groups
ggplot(mydata, aes(x = log(AdultBodyMass_g), fill = as.factor(SocialStatus))) +
  geom_histogram(bins = 20, alpha = 0.5) +
  scale_fill_manual(values = social_colours) +
  facet_wrap(~SocialStatus, ncol = 1) +
  theme(legend.position = "none") +
  theme_bw()

The optima estimates are way off. Non-social species have a long-term mean log body size estimate of 5.918899, which makes sense looking at the histograms of the data. But social species have a long-term mean log body size estimate of 18607801, which if you exponentiate it is infinity. Even King Kong was not infinitely large! Something has clearly gone wrong here, but if we had not looked at the model parameters we would have said this was the best model…It’s likely we just don’t have enough data to fit a model that is as complex as this, so the parameter optimisations are not reliable.

12.11 Diversification

BAMMtools has a several inbuilt example datasets. For this practical exercise we will use the cetacean (whales; from (steeman2009radiation?)) and the ray-finned fishes (fishes; from (rabosky2013rates?)) datasets.

Load the whales and fishes trees and BAMM outputs data into R (there is no mcmc.fishes file_).

# Load the packages
library(ape)
library(BAMMtools)
library(coda)
library(phytools)
library(viridis)

# Load whales data from BAMMtools
data(whales)
data(mcmc.whales)
data(events.whales)

# Load fishes data from BAMMtools
data(fishes)
data(mcmc.fishes)
## Warning in data(mcmc.fishes): data set 'mcmc.fishes' not found
data(events.fishes)

# Read in the tree, mcmc, and edata for whales
whales_tree <- whales
whales_mcmc <- mcmc.whales
whales_edata <- getEventData(whales, eventdata = events.whales, burnin = 0.1)
## Processing event data from data.frame
## 
## Discarded as burnin: GENERATIONS <  995000
## Analyzing  1801  samples from posterior
## 
## Setting recursive sequence on tree...
## 
## Done with recursive sequence
# Read in the tree, and edata for fishes
fishes_tree <- fishes
fishes_edata <- getEventData(fishes, eventdata = events.fishes, burnin = 0.1)
## Processing event data from data.frame
## 
## Discarded as burnin: GENERATIONS <  5
## Analyzing  46  samples from posterior
## 
## Setting recursive sequence on tree...
## 
## Done with recursive sequence

Then answer the following questions:

  1. How can we tell that the BAMM model for whales has converged? What is the effective sample size for number of shifts?
# Take a look at the plot
plot(whales_mcmc$logLik ~ whales_mcmc$generation)

# What is 10% of rows?
burnstart <- floor(0.1 * nrow(whales_mcmc))
# Remove the first 10% from the runs 
postburn <- whales_mcmc[burnstart:nrow(whales_mcmc), ]

# Extract ESS for the number of rate shifts parameter
effectiveSize(postburn$N_shifts)
##     var1 
## 1587.998
# Extract ESS for the log likelihood
effectiveSize(postburn$logLik)
##     var1 
## 1091.479

The plot looks like a furry caterpillar (!), and effective sample sizes are well over 200.

  1. What is the most common number of rate shifts in the posterior for the whales data?
# Look at the posterior for number of shifts
summary(whales_edata)
## 
## Analyzed 1801 posterior samples
## Shift posterior distribution:
## 
##          0     0.0770
##          1     0.6600
##          2     0.2100
##          3     0.0430
##          4     0.0110
##          5     0.0022
## 
## Compute credible set of shift configurations for more information:
##  See ?credibleShiftSet and ?getBestShiftConfiguration

1

  1. Plot the 95% credible set of rate shift configurations for whales.
# Extract 95% credible set of rate shift configurations
whales_css <- credibleShiftSet(whales_edata, expectedNumberOfShifts = 1, 
                        threshold = 5, set.limit = 0.95)
# Look at the summary
summary(whales_css)
## 
##  95 % credible set of rate shift configurations sampled with BAMM
## 
## Distinct shift configurations in credible set:  4
## 
## Frequency of 4 shift configurations with highest posterior probability:
## 
## 
##    rank     probability cumulative  Core_shifts
##          1 0.46418656  0.4641866          1
##          2 0.28928373  0.7534703          1
##          3 0.14158801  0.8950583          1
##          4 0.09272626  0.9877846          0
# Plot 95 % credible set of rate shift configurations
plot.credibleshiftset(whales_css)
## Omitted 0 plots

  1. Plot the mean phylorate plot for fishes.
# Plot mean phylorate plot with legend and slighting larger line width (lwd)
plot.bammdata(fishes_edata, legend = TRUE, lwd = 2)

  1. What are the mean speciation rate and the 90% posterior density for mean speciation rate in fishes?
# Extract speciation and extinction rates from the whole posterior
allrates <- getCladeRates(fishes_edata)
# Calculate overall mean speciation rate
mean(allrates$lambda)
## [1] 0.09470252
# Calculate 90% highest posterior density for speciation rate
quantile(allrates$lambda, c(0.05, 0.95))
##         5%        95% 
## 0.09020489 0.09960825

Mean = 0.09470252, 5% = 0.09020489, 95% = 0.09960825

References

Arnold, Christian, Luke J Matthews, and Charles L Nunn. 2010. “The 10kTrees Website: A New Online Resource for Primate Phylogeny.” Evolutionary Anthropology: Issues, News, and Reviews 19 (3): 114–18.
Feng, Yan-Jie, David C Blackburn, Dan Liang, David M Hillis, David B Wake, David C Cannatella, and Peng Zhang. 2017. “Phylogenomics Reveals Rapid, Simultaneous Diversification of Three Major Clades of Gondwanan Frogs at the Cretaceous–Paleogene Boundary.” Proceedings of the National Academy of Sciences 114 (29): E5864–70.
Jones, Kate E, Jon Bielby, Marcel Cardillo, Susanne A Fritz, Justin O’Dell, C David L Orme, Kamran Safi, et al. 2009. “PanTHERIA: A Species-Level Database of Life History, Ecology, and Geography of Extant and Recently Extinct Mammals: Ecological Archives E090-184.” Ecology 90 (9): 2648–48.
Thomas, Kate N, David J Gower, Rayna C Bell, Matthew K Fujita, Ryan K Schott, and Jeffrey W Streicher. 2020. “Eye Size and Investment in Frogs and Toads Correlate with Adult Habitat, Activity Pattern and Breeding Ecology.” Proceedings of the Royal Society B 287 (1935): 20201393.