1 Packages needed

library(BiodiversityR) # also loads vegan
library(pvclust)
library(ggplot2)
library(ggsci)
library(ggraph)
library(tidygraph)

2 Introduction

The main objective of this document is to show a pathway of generating dendrograms via the ggraph package for results that were obtained via pvclust. I expect that similar pathways can be used to generate dendrograms with ggraph.

3 Step 1: Conduct the pvclust analysis

3.1 Load the data

The dune meadow data sets have been used as case study in Data Analysis in Community and Landscape Ecology, the Tree Diversity Analysis manual on community ecology and biodiversity analysis (this manual can be downloaded for free from this website ) and some recent examples of generating ordination graphs, species accumulation curves and Renyi diversity profiles.

data(dune)
str(dune)
## 'data.frame':    20 obs. of  30 variables:
##  $ Achimill: num  1 3 0 0 2 2 2 0 0 4 ...
##  $ Agrostol: num  0 0 4 8 0 0 0 4 3 0 ...
##  $ Airaprae: num  0 0 0 0 0 0 0 0 0 0 ...
##  $ Alopgeni: num  0 2 7 2 0 0 0 5 3 0 ...
##  $ Anthodor: num  0 0 0 0 4 3 2 0 0 4 ...
##  $ Bellpere: num  0 3 2 2 2 0 0 0 0 2 ...
##  $ Bromhord: num  0 4 0 3 2 0 2 0 0 4 ...
##  $ Chenalbu: num  0 0 0 0 0 0 0 0 0 0 ...
##  $ Cirsarve: num  0 0 0 2 0 0 0 0 0 0 ...
##  $ Comapalu: num  0 0 0 0 0 0 0 0 0 0 ...
##  $ Eleopalu: num  0 0 0 0 0 0 0 4 0 0 ...
##  $ Elymrepe: num  4 4 4 4 4 0 0 0 6 0 ...
##  $ Empenigr: num  0 0 0 0 0 0 0 0 0 0 ...
##  $ Hyporadi: num  0 0 0 0 0 0 0 0 0 0 ...
##  $ Juncarti: num  0 0 0 0 0 0 0 4 4 0 ...
##  $ Juncbufo: num  0 0 0 0 0 0 2 0 4 0 ...
##  $ Lolipere: num  7 5 6 5 2 6 6 4 2 6 ...
##  $ Planlanc: num  0 0 0 0 5 5 5 0 0 3 ...
##  $ Poaprat : num  4 4 5 4 2 3 4 4 4 4 ...
##  $ Poatriv : num  2 7 6 5 6 4 5 4 5 4 ...
##  $ Ranuflam: num  0 0 0 0 0 0 0 2 0 0 ...
##  $ Rumeacet: num  0 0 0 0 5 6 3 0 2 0 ...
##  $ Sagiproc: num  0 0 0 5 0 0 0 2 2 0 ...
##  $ Salirepe: num  0 0 0 0 0 0 0 0 0 0 ...
##  $ Scorautu: num  0 5 2 2 3 3 3 3 2 3 ...
##  $ Trifprat: num  0 0 0 0 2 5 2 0 0 0 ...
##  $ Trifrepe: num  0 5 2 1 2 5 2 2 3 6 ...
##  $ Vicilath: num  0 0 0 0 0 0 0 0 0 1 ...
##  $ Bracruta: num  0 0 2 2 2 6 2 2 2 2 ...
##  $ Callcusp: num  0 0 0 0 0 0 0 0 0 0 ...
data(dune.env)
summary(dune.env)
##        A1         Moisture Management       Use    Manure
##  Min.   : 2.800   1:7      BF:3       Hayfield:7   0:6   
##  1st Qu.: 3.500   2:4      HF:5       Haypastu:8   1:3   
##  Median : 4.200   4:2      NM:6       Pasture :5   2:4   
##  Mean   : 4.850   5:7      SF:6                    3:4   
##  3rd Qu.: 5.725                                    4:3   
##  Max.   :11.500

3.2 Conduct a Hellinger transformation

As the pvclust function can not operate with vegan::vegdist, we will use the Euclidean distance. Prior to calculating the clustering results, the community data set is transformed by the Hellinger method as recommended in this article and also shown in a pathway of generating ordination graphs with vegan, BiodiversityR and ggplot2.

# script generated by the BiodiversityR GUI from the constrained ordination menu
dune.Hellinger <- disttransform(dune, method='hellinger')

3.3 pvclust analysis

To obtain a dendrogram that represents clustering of sites, the community data set needs to be transposed. Among the results of pvclust are a hclust object and a edges object.

set.seed(2)
dune.pv <- pvclust(t(dune.Hellinger), 
                   method.hclust="mcquitty",
                   method.dist="euclidean",
                   nboot=10000)
## Bootstrap (r = 0.5)... Done.
## Bootstrap (r = 0.6)... Done.
## Bootstrap (r = 0.7)... Done.
## Bootstrap (r = 0.8)... Done.
## Bootstrap (r = 0.9)... Done.
## Bootstrap (r = 1.0)... Done.
## Bootstrap (r = 1.1)... Done.
## Bootstrap (r = 1.2)... Done.
## Bootstrap (r = 1.3)... Done.
## Bootstrap (r = 1.4)... Done.
attributes(dune.pv)
## $names
## [1] "hclust"  "edges"   "count"   "msfit"   "nboot"   "r"       "store"  
## [8] "version"
## 
## $class
## [1] "pvclust"

It is possible now to plot the dendrogram for pvlust. The rectangles correspond to thresholds applied to the AU (Approximately Unbiased) p-value (this is a better approximation to unbiased p-values than the BP value).

plot(dune.pv)
pvrect(dune.pv, alpha=0.89, pv="au")

In the following step, the data on edges from pvclust will be added to data on nodes for the ggraph (this may seem strange here, but makes sense in terms of the pathway).

dune.pv$edges
##            si        au        bp       se.si       se.au       se.bp
## 1  0.67367308 0.8900162 0.6500593 0.009770065 0.004678329 0.001583062
## 2  0.62470794 0.8646679 0.6509359 0.010472806 0.005409584 0.001580079
## 3  0.52107100 0.8635731 0.4838776 0.012291046 0.005388623 0.001645255
## 4  0.52113062 0.8525799 0.5174110 0.012057944 0.005657406 0.001645565
## 5  0.95626554 0.9895152 0.8144038 0.002496067 0.000769902 0.001345803
## 6  0.58608873 0.8704015 0.5612605 0.011148662 0.005181026 0.001638187
## 7  0.05836824 0.6989306 0.3388617 0.015113634 0.008862102 0.001550838
## 8  0.00000000 0.6973572 0.2073154 0.000000000 0.009848418 0.001326916
## 9  0.49243363 0.8666564 0.4367195 0.013007827 0.005366611 0.001630304
## 10 0.00000000 0.8071869 0.1465370 0.000000000 0.008704205 0.001155411
## 11 0.29408270 0.8664202 0.2572468 0.018146901 0.005953144 0.001429867
## 12 0.42408147 0.8980210 0.2800115 0.016452438 0.004870102 0.001469841
## 13 0.00000000 0.7942302 0.1805106 0.000000000 0.008490440 0.001256977
## 14 0.71627120 0.9296202 0.5444732 0.009239222 0.003338046 0.001648334
## 15 0.67282027 0.8904846 0.6462837 0.009792951 0.004663206 0.001587233
## 16 0.00000000 0.7942395 0.1463469 0.000000000 0.009031488 0.001154938
## 17 0.00000000 0.6579862 0.1959493 0.000000000 0.010479640 0.001300267
## 18 0.00000000 0.5398721 0.1435282 0.000000000 0.012104246 0.001152906
## 19 1.00000000 1.0000000 1.0000000 0.000000000 0.000000000 0.000000000
##              v         c         pchi
## 1  -0.80604734 0.4205668 0.3088314904
## 2  -0.74469145 0.3568429 0.4865154078
## 3  -0.52804525 0.5684691 0.4163645695
## 4  -0.54560966 0.5019529 0.0003789444
## 5  -1.60138616 0.7071441 0.1291560223
## 6  -0.64122844 0.4870626 0.0199835695
## 7  -0.05287773 0.4684495 0.2447419111
## 8   0.14947842 0.6662930 0.2247349650
## 9  -0.47571606 0.6350079 0.0258432352
## 10  0.09191271 0.9594893 0.6549884988
## 11 -0.22888526 0.8807420 0.0312624364
## 12 -0.34377404 0.9265815 0.4122681792
## 13  0.04611690 0.8673041 0.5504418008
## 14 -0.79233900 0.6806293 0.5457562329
## 15 -0.80220781 0.4269015 0.7693126115
## 16  0.11550532 0.9367252 0.9145713157
## 17  0.22460298 0.6315762 0.9794099838
## 18  0.48224497 0.5823565 0.7408072082
## 19  0.00000000 0.0000000 0.0000000000

4 Step 2: Add information for nodes

4.1 Make sure that all heights are unique

When adding data on nodes (section 4.3), the nodes will be linked via the height variable. It is therefore necessary that all the heights are unique. One method of doing this is by adding a very small but also unique number…

anyDuplicated(dune.pv$hclust$height)
## [1] 0
if (anyDuplicated(dune.pv$hclust$height) != 0) {
  .Machine$double.eps
  small.add <- seq_along(dune.pv$hclust$height) * 1e-15
  dune.pv$hclust$height <- dune.pv$hclust$height + small.add
}

anyDuplicated(dune.pv$hclust$height)
## [1] 0

4.2 Obtain data sets for nodes and edges

When plotting a hclust object, ggraph internally converts the object to a tbl_graph object. The pathway shown here consists of adding variables to the nodes and edges of the tbl_graph data sets.

dune.graph2 <- as.list(as_tbl_graph(dune.pv$hclust))

dune.nodes <- data.frame(dune.graph2$nodes)
dune.edges <- data.frame(dune.graph2$edges)

4.3 Add information on nodes about the merging process

Although the main fields that are needed are the ID and the clustering height, information is also added in the merging process. In the notations used by hclust, negative numbers refer to agglomerations of singletons, whereas positive numbers refer to non-singletons. The information that is added thus shows that row 3 is a branch node at height 0.6159… that has ID 6 (as also in the pvclust dendrogram above) and that corresponds to the merging of sites 12 and 13.

merge.data <- data.frame(cbind(dune.pv$hclust$merge, dune.pv$hclust$height))
names(merge.data) <- c("m1", "m2", "height")
merge.data$ID <- c(1:nrow(merge.data))
 
dune.nodes2 <- left_join(dune.nodes, merge.data, by="height")
head(dune.nodes2)
##      height  leaf label members  m1  m2 ID
## 1 0.0000000  TRUE    12       1  NA  NA NA
## 2 0.0000000  TRUE    13       1  NA  NA NA
## 3 0.6159341 FALSE             2 -12 -13  6
## 4 0.0000000  TRUE     8       1  NA  NA NA
## 5 0.0000000  TRUE     9       1  NA  NA NA
## 6 0.0000000  TRUE     3       1  NA  NA NA

4.4 Add probability values

Via the ID field (the sequence of hierarchical clustering), probability values are now added to the nodes.

edges.pv <- data.frame(dune.pv$edges)
edges.pv$ID <- c(1:nrow(edges.pv))

dune.nodes3 <- left_join(dune.nodes2, edges.pv, by="ID")
head(dune.nodes3)
##      height  leaf label members  m1  m2 ID        si        au        bp
## 1 0.0000000  TRUE    12       1  NA  NA NA        NA        NA        NA
## 2 0.0000000  TRUE    13       1  NA  NA NA        NA        NA        NA
## 3 0.6159341 FALSE             2 -12 -13  6 0.5860887 0.8704015 0.5612605
## 4 0.0000000  TRUE     8       1  NA  NA NA        NA        NA        NA
## 5 0.0000000  TRUE     9       1  NA  NA NA        NA        NA        NA
## 6 0.0000000  TRUE     3       1  NA  NA NA        NA        NA        NA
##        se.si       se.au       se.bp          v         c       pchi
## 1         NA          NA          NA         NA        NA         NA
## 2         NA          NA          NA         NA        NA         NA
## 3 0.01114866 0.005181026 0.001638187 -0.6412284 0.4870626 0.01998357
## 4         NA          NA          NA         NA        NA         NA
## 5         NA          NA          NA         NA        NA         NA
## 6         NA          NA          NA         NA        NA         NA

4.5 Add environmental data to the leaves

Via the label of the leaves, information on environmental descriptors are added for the leaves.

dune.env$label <- rownames(dune.env) 
dune.nodes4 <- left_join(dune.nodes3, dune.env, by="label")
head(dune.nodes4)
##      height  leaf label members  m1  m2 ID        si        au        bp
## 1 0.0000000  TRUE    12       1  NA  NA NA        NA        NA        NA
## 2 0.0000000  TRUE    13       1  NA  NA NA        NA        NA        NA
## 3 0.6159341 FALSE             2 -12 -13  6 0.5860887 0.8704015 0.5612605
## 4 0.0000000  TRUE     8       1  NA  NA NA        NA        NA        NA
## 5 0.0000000  TRUE     9       1  NA  NA NA        NA        NA        NA
## 6 0.0000000  TRUE     3       1  NA  NA NA        NA        NA        NA
##        se.si       se.au       se.bp          v         c       pchi  A1
## 1         NA          NA          NA         NA        NA         NA 5.8
## 2         NA          NA          NA         NA        NA         NA 6.0
## 3 0.01114866 0.005181026 0.001638187 -0.6412284 0.4870626 0.01998357  NA
## 4         NA          NA          NA         NA        NA         NA 4.2
## 5         NA          NA          NA         NA        NA         NA 3.7
## 6         NA          NA          NA         NA        NA         NA 4.3
##   Moisture Management      Use Manure
## 1        4         SF Haypastu      2
## 2        5         SF Haypastu      3
## 3     <NA>       <NA>     <NA>   <NA>
## 4        5         HF  Pasture      3
## 5        4         HF Hayfield      1
## 6        2         SF Haypastu      4

5 Step 3: Add information to edges

Now via the from field, information on probability values can be added to edges.

dune.nodes4$SEQ <- c(1:nrow(dune.nodes4))

dune.edges2 <- left_join(dune.edges, 
                         dune.nodes4[, c("SEQ", "height", "au")], 
                         by=c("from" = "SEQ"))
head(dune.edges2)
##   from to    height        au
## 1    3  1 0.6159341 0.8704015
## 2    3  2 0.6159341 0.8704015
## 3    8  6 0.5400578 0.8635731
## 4    8  7 0.5400578 0.8635731
## 5    9  5 0.6578777 0.6973572
## 6    9  8 0.6578777 0.6973572

6 Step 4: Generate the dendrogram with ggraph

With the various variables added to the nodes and the edges, a new tbl_graph object is created.

dune.graph2 <- tbl_graph(nodes=dune.nodes4, edges=dune.edges2, directed=TRUE)
dune.graph2
## # A tbl_graph: 39 nodes and 38 edges
## #
## # A rooted tree
## #
## # Node Data: 39 x 22 (active)
##   height leaf  label members    m1    m2    ID     si     au     bp   se.si
##    <dbl> <lgl> <chr>   <int> <dbl> <dbl> <int>  <dbl>  <dbl>  <dbl>   <dbl>
## 1  0     TRUE  "12"        1    NA    NA    NA NA     NA     NA     NA     
## 2  0     TRUE  "13"        1    NA    NA    NA NA     NA     NA     NA     
## 3  0.616 FALSE ""          2   -12   -13     6  0.586  0.870  0.561  0.0111
## 4  0     TRUE  "8"         1    NA    NA    NA NA     NA     NA     NA     
## 5  0     TRUE  "9"         1    NA    NA    NA NA     NA     NA     NA     
## 6  0     TRUE  "3"         1    NA    NA    NA NA     NA     NA     NA     
## # ... with 33 more rows, and 11 more variables: se.au <dbl>, se.bp <dbl>,
## #   v <dbl>, c <dbl>, pchi <dbl>, A1 <dbl>, Moisture <ord>, Management <fct>,
## #   Use <ord>, Manure <ord>, SEQ <int>
## #
## # Edge Data: 38 x 4
##    from    to height    au
##   <int> <int>  <dbl> <dbl>
## 1     3     1  0.616 0.870
## 2     3     2  0.616 0.870
## 3     8     6  0.540 0.864
## # ... with 35 more rows

It now has become relatively straightforward to generate the ggraph by accessing the variables in various aesthetics calls.

First the theme is set to an empty canvas.

BioR.theme <- theme(
        panel.background = element_blank(),
        panel.border = element_blank(),
        panel.grid = element_blank(),
        axis.line.x = element_blank(), 
        axis.line.y = element_line("gray25"),
        axis.ticks.y = element_line("gray25"),
        text = element_text(size = 12),
        axis.text.y = element_text(size = 10, colour = "gray25"),
        axis.text.x = element_blank(),
        axis.title = element_blank(),
        legend.title = element_text(size = 14),
        legend.text = element_text(size = 14),
        legend.key = element_blank())

And now the dendrogram is created.

Within the script, the width of edges and nodes reflects AU. The colour reflects a threshold of 0.89 for the AU.

ggraph1 <- ggraph(dune.graph2, layout="dendrogram", circular=FALSE, height=height) +
  scale_y_continuous(sec.axis = dup_axis(name=NULL)) +    
  geom_edge_bend(aes(edge_width=au, colour=au>=0.89), 
                 alpha=0.7, show.legend=FALSE) +
  geom_node_point(aes(filter=leaf, shape=Management), 
                  size=5, colour="black") +
  geom_node_point(aes(size=au, fill=au>=0.89), 
                  shape=21, show.legend=FALSE) +
  geom_node_text(aes(filter=leaf, label=label), 
                 hjust=1, nudge_y=-0.05, angle=90) +
  geom_node_text(aes(filter=!leaf, label=as.character(round(au, 2))),
                 nudge_y=-0.05) +
  BioR.theme +
  scale_fill_npg() +
  scale_edge_colour_manual(values=pal_npg()(2))


ggraph1
## Warning: Removed 20 rows containing missing values (geom_point).

An alternative dendrogram is circular.

ggraph2 <- ggraph(dune.graph2, layout="dendrogram", circular=TRUE, height=NA) +
  geom_edge_bend(aes(edge_width=au, colour=au>=0.89), 
                 alpha=0.7, show.legend=FALSE) +
  geom_node_point(aes(filter=leaf, shape=Management), 
                  alpha=0.7, size=8, colour="darkolivegreen4") +
  geom_node_text(aes(filter=leaf, label=label), 
                 hjust=0.5, angle=0, colour="black") +
  geom_node_text(aes(filter=!leaf, label=as.character(round(au, 2))),
                 colour="black", hjust=0.5) +
  BioR.theme +
  theme(axis.line.y = element_blank()) +
  theme(axis.text.y = element_blank()) +
  theme(axis.ticks.y = element_blank()) +
  scale_fill_npg() +
  scale_edge_colour_manual(values=pal_npg()(2)) +
  coord_fixed()

ggraph2

7 Making a hanging tree

7.1 Get data from heights of ‘from’ edge

dune.nodes5 <- dune.nodes4
dune.nodes5$SEQ <- 1:nrow(dune.nodes5)
dune.nodes5$height.old <- dune.nodes5$height

from.heights <- left_join(dune.nodes4[dune.nodes4$leaf == TRUE, c("label", "SEQ")],
                          dune.edges2[, c("to", "height")],
                          by=c("SEQ" = "to"))

head(from.heights)
##   label SEQ    height
## 1    12   1 0.6159341
## 2    13   2 0.6159341
## 3     8   4 0.6957780
## 4     9   5 0.6578777
## 5     3   6 0.5400578
## 6     4   7 0.5400578

7.2 Reduce the heights by desired amount of ‘hanging’

from.heights$hang.height <- from.heights$height - 0.2

dune.nodes6 <- left_join(dune.nodes5, 
                         from.heights[, c("label", "hang.height")], 
                         by="label")

dune.nodes6[dune.nodes6$leaf == TRUE, "height"] <- dune.nodes6[dune.nodes6$leaf == TRUE, "hang.height"]

head(dune.nodes6)
##      height  leaf label members  m1  m2 ID        si        au        bp
## 1 0.4159341  TRUE    12       1  NA  NA NA        NA        NA        NA
## 2 0.4159341  TRUE    13       1  NA  NA NA        NA        NA        NA
## 3 0.6159341 FALSE             2 -12 -13  6 0.5860887 0.8704015 0.5612605
## 4 0.4957780  TRUE     8       1  NA  NA NA        NA        NA        NA
## 5 0.4578777  TRUE     9       1  NA  NA NA        NA        NA        NA
## 6 0.3400578  TRUE     3       1  NA  NA NA        NA        NA        NA
##        se.si       se.au       se.bp          v         c       pchi  A1
## 1         NA          NA          NA         NA        NA         NA 5.8
## 2         NA          NA          NA         NA        NA         NA 6.0
## 3 0.01114866 0.005181026 0.001638187 -0.6412284 0.4870626 0.01998357  NA
## 4         NA          NA          NA         NA        NA         NA 4.2
## 5         NA          NA          NA         NA        NA         NA 3.7
## 6         NA          NA          NA         NA        NA         NA 4.3
##   Moisture Management      Use Manure SEQ height.old hang.height
## 1        4         SF Haypastu      2   1  0.0000000   0.4159341
## 2        5         SF Haypastu      3   2  0.0000000   0.4159341
## 3     <NA>       <NA>     <NA>   <NA>   3  0.6159341          NA
## 4        5         HF  Pasture      3   4  0.0000000   0.4957780
## 5        4         HF Hayfield      1   5  0.0000000   0.4578777
## 6        2         SF Haypastu      4   6  0.0000000   0.3400578

7.3 Create the new tbl_graph object

dune.graph3 <- tbl_graph(nodes=dune.nodes6, edges=dune.edges2, directed=TRUE)
dune.graph3
## # A tbl_graph: 39 nodes and 38 edges
## #
## # A rooted tree
## #
## # Node Data: 39 x 24 (active)
##   height leaf  label members    m1    m2    ID     si     au     bp   se.si
##    <dbl> <lgl> <chr>   <int> <dbl> <dbl> <int>  <dbl>  <dbl>  <dbl>   <dbl>
## 1  0.416 TRUE  "12"        1    NA    NA    NA NA     NA     NA     NA     
## 2  0.416 TRUE  "13"        1    NA    NA    NA NA     NA     NA     NA     
## 3  0.616 FALSE ""          2   -12   -13     6  0.586  0.870  0.561  0.0111
## 4  0.496 TRUE  "8"         1    NA    NA    NA NA     NA     NA     NA     
## 5  0.458 TRUE  "9"         1    NA    NA    NA NA     NA     NA     NA     
## 6  0.340 TRUE  "3"         1    NA    NA    NA NA     NA     NA     NA     
## # ... with 33 more rows, and 13 more variables: se.au <dbl>, se.bp <dbl>,
## #   v <dbl>, c <dbl>, pchi <dbl>, A1 <dbl>, Moisture <ord>, Management <fct>,
## #   Use <ord>, Manure <ord>, SEQ <int>, height.old <dbl>, hang.height <dbl>
## #
## # Edge Data: 38 x 4
##    from    to height    au
##   <int> <int>  <dbl> <dbl>
## 1     3     1  0.616 0.870
## 2     3     2  0.616 0.870
## 3     8     6  0.540 0.864
## # ... with 35 more rows

7.4 Generate the dendrogram

ggraph3 <- ggraph(dune.graph3, layout="dendrogram", circular=FALSE, height=height) +
  scale_y_continuous(sec.axis = dup_axis(name=NULL)) +    
  geom_edge_bend(aes(edge_width=au, colour=au>=0.89), 
                 alpha=0.7, show.legend=FALSE) +
  geom_node_point(aes(filter=leaf, shape=Management), 
                  size=5, colour="black") +
  geom_node_point(aes(size=au, fill=au>=0.89), 
                  shape=21, show.legend=FALSE) +
  geom_node_text(aes(filter=leaf, label=label), 
                 hjust=1, nudge_y=-0.05, angle=90) +
  geom_node_text(aes(filter=!leaf, label=as.character(round(au, 2))),
                 nudge_y=-0.05) +
  BioR.theme +
  scale_fill_npg() +
  scale_edge_colour_manual(values=pal_npg()(2))


ggraph3
## Warning: Removed 20 rows containing missing values (geom_point).

8 Session Information

sessionInfo()
## R version 4.0.2 (2020-06-22)
## Platform: x86_64-w64-mingw32/x64 (64-bit)
## Running under: Windows 10 x64 (build 18363)
## 
## Matrix products: default
## 
## locale:
## [1] LC_COLLATE=English_United Kingdom.1252 
## [2] LC_CTYPE=English_United Kingdom.1252   
## [3] LC_MONETARY=English_United Kingdom.1252
## [4] LC_NUMERIC=C                           
## [5] LC_TIME=English_United Kingdom.1252    
## 
## attached base packages:
## [1] tcltk     stats     graphics  grDevices utils     datasets  methods  
## [8] base     
## 
## other attached packages:
##  [1] tidygraph_1.2.0      ggraph_2.0.4         ggsci_2.9           
##  [4] ggplot2_3.3.2        pvclust_2.2-0        BiodiversityR_2.12-2
##  [7] rgl_0.100.54         vegan3d_1.1-2        vegan_2.5-6         
## [10] lattice_0.20-41      permute_0.9-5       
## 
## loaded via a namespace (and not attached):
##   [1] minqa_1.2.4             colorspace_1.4-1        ellipsis_0.3.1         
##   [4] class_7.3-17            rio_0.5.16              htmlTable_2.0.0        
##   [7] base64enc_0.1-3         rstudioapi_0.11         farver_2.0.3           
##  [10] graphlayouts_0.7.1      ggrepel_0.8.2           fansi_0.4.1            
##  [13] splines_4.0.2           knitr_1.28              effects_4.1-4          
##  [16] polyclip_1.10-0         Formula_1.2-3           jsonlite_1.6.1         
##  [19] nloptr_1.2.2.1          cluster_2.1.0           Rcmdr_2.6-2            
##  [22] png_0.1-7               ggforce_0.3.2           shiny_1.4.0.2          
##  [25] compiler_4.0.2          backports_1.1.7         assertthat_0.2.1       
##  [28] Matrix_1.2-18           fastmap_1.0.1           cli_2.0.2              
##  [31] survey_4.0              tweenr_1.0.1            later_1.1.0.1          
##  [34] tcltk2_1.2-11           acepack_1.4.1           htmltools_0.5.0        
##  [37] tools_4.0.2             igraph_1.2.6            gtable_0.3.0           
##  [40] glue_1.4.1              dplyr_1.0.2             Rcpp_1.0.4.6           
##  [43] carData_3.0-4           cellranger_1.1.0        vctrs_0.3.4            
##  [46] nlme_3.1-148            crosstalk_1.1.0.1       xfun_0.15              
##  [49] stringr_1.4.0           openxlsx_4.1.5          lme4_1.1-23            
##  [52] mime_0.9                miniUI_0.1.1.1          lifecycle_0.2.0        
##  [55] RcmdrMisc_2.7-0         statmod_1.4.34          MASS_7.3-51.6          
##  [58] zoo_1.8-8               scales_1.1.1            hms_0.5.3              
##  [61] promises_1.1.1          parallel_4.0.2          sandwich_2.5-1         
##  [64] RColorBrewer_1.1-2      yaml_2.2.1              curl_4.3               
##  [67] gridExtra_2.3           rpart_4.1-15            latticeExtra_0.6-29    
##  [70] stringi_1.4.6           nortest_1.0-4           e1071_1.7-3            
##  [73] checkmate_2.0.0         boot_1.3-25             zip_2.0.4              
##  [76] manipulateWidget_0.10.1 rlang_0.4.8             pkgconfig_2.0.3        
##  [79] evaluate_0.14           purrr_0.3.4             labeling_0.3           
##  [82] htmlwidgets_1.5.1       tidyselect_1.1.0        magrittr_1.5           
##  [85] R6_2.4.1                generics_0.1.0          Hmisc_4.4-0            
##  [88] DBI_1.1.0               pillar_1.4.4            haven_2.3.1            
##  [91] foreign_0.8-80          withr_2.2.0             mgcv_1.8-31            
##  [94] survival_3.1-12         scatterplot3d_0.3-41    abind_1.4-5            
##  [97] nnet_7.3-14             tibble_3.0.1            crayon_1.3.4           
## [100] car_3.0-8               utf8_1.1.4              relimp_1.0-5           
## [103] rmarkdown_2.3           viridis_0.5.1           jpeg_0.1-8.1           
## [106] grid_4.0.2              readxl_1.3.1            data.table_1.12.8      
## [109] forcats_0.5.0           digest_0.6.25           webshot_0.5.2          
## [112] xtable_1.8-4            tidyr_1.1.2             httpuv_1.5.4           
## [115] munsell_0.5.0           viridisLite_0.3.0       mitools_2.4