diff --git a/.travis.yml b/.travis.yml index 8819ed9..f841035 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,7 +13,6 @@ matrix: before_deploy: - Rscript -e 'remotes::install_cran("pkgdown")' - Rscript -e 'remotes::install_github("maurolepore/pkgdoc")' - - Rscript -e 'install.packages("DT")' deploy: provider: script script: Rscript -e 'pkgdown::deploy_site_github()' @@ -21,6 +20,4 @@ matrix: - r: oldrel - r: 3.3 - r: 3.2 - allow_failures: - - r: 3.2 diff --git a/DESCRIPTION b/DESCRIPTION index 397b189..3a88295 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -104,10 +104,10 @@ Imports: cli (>= 1.0.1), crayon (>= 1.3.4), dplyr (>= 0.7.8), - fgeo.analyze (>= 1.1.2), - fgeo.plot (>= 1.1.1), - fgeo.tool (>= 1.2.1), - fgeo.x (>= 1.1.0), + fgeo.analyze (>= 1.1.3), + fgeo.plot (>= 1.1.3), + fgeo.tool (>= 1.2.2), + fgeo.x (>= 1.1.2), glue (>= 1.3.0), magrittr (>= 1.5), purrr (>= 0.3.0), @@ -117,12 +117,12 @@ Imports: Suggests: covr (>= 3.2.1), DT (>= 0.5), + kableExtra (>= 1.0.1), knitr (>= 1.21), rmarkdown (>= 1.11), spelling (>= 2.0), testthat (>= 2.0.1) -Additional_repositories: https://cran.rstudio.com/, - https://forestgeo.github.io/drat/ +Additional_repositories: https://forestgeo.github.io/drat/ Encoding: UTF-8 Language: en-US LazyData: true diff --git a/NEWS.md b/NEWS.md index f6ea639..093bae5 100644 --- a/NEWS.md +++ b/NEWS.md @@ -18,6 +18,6 @@ * Tidy dependencies. -# fgeo 1.0.0 ([GitHub](https://github.com/forestgeo/fgeo/releases) release) +# fgeo 1.0.0 ([GitHub](https://github.com/forestgeo/fgeo/releases)) * Internal release. diff --git a/ru.sh b/ru.sh new file mode 100644 index 0000000..b26be8c --- /dev/null +++ b/ru.sh @@ -0,0 +1,4 @@ +git checkout master +git fetch upstream +git reset --hard upstream/master +git remote prune origin diff --git a/vignettes/siteonly/pandoc53547b2d4760.html b/vignettes/siteonly/pandoc53547b2d4760.html deleted file mode 100644 index b6dfc4f..0000000 --- a/vignettes/siteonly/pandoc53547b2d4760.html +++ /dev/null @@ -1,769 +0,0 @@ - - - - - - - - - - - - - - -Get started - - - - - - - - - - - - - - - - - - -

Get started

- - - -

This article shows some of the key features of fgeo applied to an exploratory data analysis. For a deeper and general approach to exploratory data analysis, see this book section. A version adapted for ForestGEO is available here.

-
-

Packages

-

In every new R session you need to “open” fgeo with library().

-
library(fgeo)
-#> -- Attaching packages ------------------------------------------------ fgeo 0.0.0.9002 --
-#> v fgeo.x       0.0.0.9000     v fgeo.analyze 0.0.0.9003
-#> v fgeo.map     0.0.0.9402     v fgeo.tool    0.0.0.9005
-#> -- Conflicts -------------------------------------------------------- fgeo_conflicts() --
-#> x fgeo.tool::filter() masks stats::filter()
-

You may suppress the startup message with suppressPackageStartupMessages() or add options("fgeo.quiet" = TRUE) to .Rprofile (see usethis::edit_r_profile()).

-
-
-

Data

-

You may use you own data but fgeo comes with some example datasets.

-
fgeo_help("datasets")
-

We will use a dataset of stems censused in one hectare from the forest plot in Luquillo, Puerto Rico (https://forestgeo.si.edu/sites/north-america/luquillo).

-
stem <- download_data("luquillo_stem_random")
-str(stem)
-#> Classes 'tbl_df', 'tbl' and 'data.frame':    7920 obs. of  19 variables:
-#>  $ treeID   : int  104 119 180 180 180 180 602 631 647 1086 ...
-#>  $ stemID   : int  143 158 222 223 224 225 736 775 793 1339 ...
-#>  $ tag      : chr  "10009" "100104" "100171" "100171" ...
-#>  $ StemTag  : chr  "10009" "100104" "100095" "100096" ...
-#>  $ sp       : chr  "DACEXC" "MYRSPL" "CASARB" "CASARB" ...
-#>  $ quadrat  : chr  "113" "1021" "921" "921" ...
-#>  $ gx       : num  10.3 182.9 164.6 164.6 164.6 ...
-#>  $ gy       : num  245 410 410 410 410 ...
-#>  $ MeasureID: int  143 158 222 223 224 225 736 775 793 1339 ...
-#>  $ CensusID : int  1 1 1 1 1 1 1 1 1 1 ...
-#>  $ dbh      : num  115 16 17.2 11.7 80 19.4 24.1 100 146 165 ...
-#>  $ pom      : chr  "1.2" "1.3" "1.3" "1.3" ...
-#>  $ hom      : num  1.2 1.3 1.3 1.3 1.3 1.3 1.3 1.3 1.3 1.3 ...
-#>  $ ExactDate: Date, format: "1991-06-11" "1993-07-28" ...
-#>  $ DFstatus : chr  "alive" "alive" "alive" "alive" ...
-#>  $ codes    : chr  "MAIN;A" "MAIN;A" "SPROUT;A" "SPROUT;A" ...
-#>  $ countPOM : num  1 1 1 1 1 1 1 1 1 1 ...
-#>  $ status   : chr  "A" "A" "A" "A" ...
-#>  $ date     : num  11484 12262 12263 12263 12263 ...
-

This dataset comes with multiple censuses but we’ll work with the latest one.

-
unique(stem$CensusID)
-#> [1] 1 2 3 4 5 6
-
-stem <- filter(stem, CensusID %in% max(unique(stem$CensusID)))
-unique(stem$CensusID)
-#> [1] 6
-

For a description of the columns, see ?data_dictionary.

-
data_dictionary <- download_data("data_dictionary")
-str(data_dictionary)
-#> Classes 'tbl_df', 'tbl' and 'data.frame':    242 obs. of  3 variables:
-#>  $ table      : chr  "Census" "Census" "Census" "Census" ...
-#>  $ column     : chr  "CensusID" "PlotID" "PlotCensusNumber" "StartDate" ...
-#>  $ description: chr  "Primary key, an integer  automatically generated to uniquely identify a census." "Foreign Key to Site table." "Integer census number for an individual plot, 1=first census, 2=second census, etc. If there are more than one "| __truncated__ "Date on which the first measurement of the census was taken." ...
-
-cols <- names(stem)
-filter(data_dictionary, column %in% cols)
-#> # A tibble: 20 x 3
-#>    table           column   description                                    
-#>    <chr>           <chr>    <chr>                                          
-#>  1 Census          CensusID Primary key, an integer  automatically generat~
-#>  2 CensusQuadrat   CensusID Foreign Key to Census table.                   
-#>  3 DataCollection  CensusID Foreign Key to Census table.                   
-#>  4 DBH             CensusID Foreign Key to Census table.                   
-#>  5 DBH             ExactDa~ Date on which the measurement was taken.       
-#>  6 DBHAttributes   CensusID Foreign Key to Census table.                   
-#>  7 Measurement     Measure~ Primary key, an integer  automatically generat~
-#>  8 Measurement     CensusID Foreign Key to Census table.                   
-#>  9 Measurement     ExactDa~ "Date on which measurement has been done  (for~
-#> 10 MeasurementAtt~ Measure~ Foreign Key to Measurement table.              
-#> 11 MeasurementAtt~ CensusID Foreign Key to Census table.                   
-#> 12 RemeasAttribs   CensusID Foreign Key to Census table.                   
-#> 13 Remeasurement   CensusID Foreign Key to  Census table.                  
-#> 14 Remeasurement   ExactDa~ "Date of remeasurement.  (format is yyyy-mm-dd~
-#> 15 SpeciesInvento~ CensusID Foreign Key to  Census table.                  
-#> 16 Stem            StemTag  The stem tag used in the field to identify the~
-#> 17 TreeAttributes  CensusID Foreign Key to  Census table.                  
-#> 18 ViewFullTable   StemTag  The stem tag used in the field to identify the~
-#> 19 ViewFullTable   CensusID Foreign Key to  Census table.                  
-#> 20 ViewFullTable   ExactDa~ Date on which the measurement was taken (forma~
-
-
-

Demography

-
census5 <- download_data("luquillo_tree5_random")
-census6 <- download_data("luquillo_tree6_random")
-
-recruitment_ctfs(census5, census6)
-#> Detected dbh ranges:
-#>   * `census1` = 10-955.
-#>   * `census2` = 10.2-992.
-#> Using dbh `mindbh = 0` and above.
-#> $N2
-#> [1] 809
-#> 
-#> $R
-#> [1] 43
-#> 
-#> $rate
-#> [1] 0.01205766
-#> 
-#> $lower
-#> [1] 0.008953252
-#> 
-#> $upper
-#> [1] 0.01622177
-#> 
-#> $time
-#> [1] 4.529631
-#> 
-#> $date1
-#> [1] 18938.5
-#> 
-#> $date2
-#> [1] 20594.2
-

With to_df() we convert the result of any demography function to a tibble – a convenient dataframe.

-
to_df(
-  recruitment_ctfs(census5, census6)
-)
-#> Detected dbh ranges:
-#>   * `census1` = 10-955.
-#>   * `census2` = 10.2-992.
-#> Using dbh `mindbh = 0` and above.
-#> # A tibble: 1 x 8
-#>      N2     R   rate   lower  upper  time  date1  date2
-#>   <dbl> <dbl>  <dbl>   <dbl>  <dbl> <dbl>  <dbl>  <dbl>
-#> 1   809    43 0.0121 0.00895 0.0162  4.53 18939. 20594.
-

We can aggregate results by any number of variables:

- -
to_df(recruitment_ctfs(census5, census6, split1 = census5$sp))
-#> Detected dbh ranges:
-#>   * `census1` = 10-955.
-#>   * `census2` = 10.2-992.
-#> Using dbh `mindbh = 0` and above.
-#> # A tibble: 73 x 9
-#>    groups    N2     R     rate    lower    upper  time  date1  date2
-#>    <chr>  <dbl> <dbl>    <dbl>    <dbl>    <dbl> <dbl>  <dbl>  <dbl>
-#>  1 ALCFLO     3     0   0       0         0.205   4.51 18980. 20626 
-#>  2 ALCLAT     0     0  NA      NA        NA      NA    18945     NA 
-#>  3 ANDINE     2     0   0       0         0.273   4.50 18979  20623 
-#>  4 ARDGLA     2     0   0       0         0.269   4.56 18855  20522 
-#>  5 ARTALT     1     0   0       0         0.410   4.50 18904  20548 
-#>  6 BRUPOR     0     0  NA      NA        NA      NA    18893     NA 
-#>  7 BUCTET     7     0   0       0         0.102   4.54 18902  20570.
-#>  8 BYRSPI    10     0   0       0         0.0742  4.52 18983. 20650.
-#>  9 CALCAL     1     1 Inf      NA       Inf      NA       NA  20626 
-#> 10 CASARB    70     5   0.0164  0.00712   0.0377  4.52 18984. 20637.
-#> # ... with 63 more rows
- -
sp_quadrat <- interaction(census5$sp, census5$quadrat)
-by_many <- recruitment_ctfs(census5, census6, split1 = sp_quadrat)
-#> Detected dbh ranges:
-#>   * `census1` = 10-955.
-#>   * `census2` = 10.2-992.
-#> Using dbh `mindbh = 0` and above.
-to_df(by_many)
-#> # A tibble: 26,207 x 9
-#>    groups         N2     R  rate lower  upper  time date1 date2
-#>    <chr>       <dbl> <dbl> <dbl> <dbl>  <dbl> <dbl> <dbl> <dbl>
-#>  1 PREMON.1001     1     0     0     0  0.399  4.62 18806 20495
-#>  2 DACEXC.1002     1     0     0     0  0.399  4.63 18805 20495
-#>  3 DACEXC.1005     1     0     0     0  0.404  4.56 18849 20515
-#>  4 TRIPAL.1005     0     0    NA    NA NA     NA    18849    NA
-#>  5 MANBID.1006     1     0     0     0  0.404  4.56 18849 20515
-#>  6 EUGSTA.1007     1     0     0     0  0.410  4.50 18891 20534
-#>  7 MANBID.1007     1     0     0     0  0.410  4.50 18892 20535
-#>  8 MATDOM.1007     1     0     0     0  0.410  4.50 18891 20535
-#>  9 MICPRA.1007     0     0    NA    NA NA     NA    18891    NA
-#> 10 SLOBER.1007     0     0    NA    NA NA     NA    18890    NA
-#> # ... with 26,197 more rows
-

To separate the multiple groups we can use tidyr::separate().

-
tidyr::separate(to_df(by_many), groups, into = c("species", "quadrats"))
-#> # A tibble: 26,207 x 10
-#>    species quadrats    N2     R  rate lower  upper  time date1 date2
-#>    <chr>   <chr>    <dbl> <dbl> <dbl> <dbl>  <dbl> <dbl> <dbl> <dbl>
-#>  1 PREMON  1001         1     0     0     0  0.399  4.62 18806 20495
-#>  2 DACEXC  1002         1     0     0     0  0.399  4.63 18805 20495
-#>  3 DACEXC  1005         1     0     0     0  0.404  4.56 18849 20515
-#>  4 TRIPAL  1005         0     0    NA    NA NA     NA    18849    NA
-#>  5 MANBID  1006         1     0     0     0  0.404  4.56 18849 20515
-#>  6 EUGSTA  1007         1     0     0     0  0.410  4.50 18891 20534
-#>  7 MANBID  1007         1     0     0     0  0.410  4.50 18892 20535
-#>  8 MATDOM  1007         1     0     0     0  0.410  4.50 18891 20535
-#>  9 MICPRA  1007         0     0    NA    NA NA     NA    18891    NA
-#> 10 SLOBER  1007         0     0    NA    NA NA     NA    18890    NA
-#> # ... with 26,197 more rows
-

The same works for mortality and growth.

-
to_df(mortality_ctfs(census5, census6, split1 = sp_quadrat))
-#> Detected dbh ranges:
-#>   * `census1` = 10-955.
-#>   * `census2` = 10.2-992.
-#> Using dbh `mindbh = 0` and above.
-#> # A tibble: 26,207 x 10
-#>    groups          N     D  rate  lower   upper  time date1 date2 dbhmean
-#>    <chr>       <dbl> <dbl> <dbl>  <dbl>   <dbl> <dbl> <dbl> <dbl>   <dbl>
-#>  1 PREMON.1001     1     0     0 0        0.399  4.62 18806 20495   136  
-#>  2 DACEXC.1002     1     0     0 0        0.399  4.63 18805 20495   419  
-#>  3 DACEXC.1005     1     0     0 0        0.404  4.56 18849 20515    58  
-#>  4 TRIPAL.1005     1     1   Inf 0.0377 Inf      4.56 18849 20515    42.5
-#>  5 MANBID.1006     1     0     0 0        0.404  4.56 18849 20515    30.6
-#>  6 EUGSTA.1007     1     0     0 0        0.410  4.50 18891 20534    55  
-#>  7 MANBID.1007     1     0     0 0        0.410  4.50 18892 20535    15  
-#>  8 MATDOM.1007     1     0     0 0        0.410  4.50 18891 20535   240  
-#>  9 MICPRA.1007     1     1   Inf 0.0383 Inf      4.50 18891 20534    12.2
-#> 10 SLOBER.1007     1     1   Inf 0.0382 Inf      4.50 18890 20534   101  
-#> # ... with 26,197 more rows
-
-to_df(growth_ctfs(census5, census6, split1 = sp_quadrat))
-#> Detected dbh ranges:
-#>   * `census1` = 10-955.
-#>   * `census2` = 10.2-992.
-#> Using dbh `mindbh = 0` and above.
-#> # A tibble: 26,207 x 8
-#>    groups          rate     N  clim dbhmean  time date1 date2
-#>    <chr>          <dbl> <dbl> <dbl>   <dbl> <dbl> <dbl> <dbl>
-#>  1 PREMON.1001  -0.216      1    NA   136    4.62 18806 20495
-#>  2 DACEXC.1002   0.864      1    NA   419    4.63 18805 20495
-#>  3 DACEXC.1005   0.438      1    NA    58    4.56 18849 20515
-#>  4 TRIPAL.1005  NA          0    NA    NA   NA       NA    NA
-#>  5 MANBID.1006  -0.0219     1    NA    30.6  4.56 18849 20515
-#>  6 EUGSTA.1007   0.222      1    NA    55    4.50 18891 20534
-#>  7 MANBID.1007  -0.111      1    NA    15    4.50 18892 20535
-#>  8 MATDOM.1007   0          1    NA   240    4.50 18891 20535
-#>  9 MICPRA.1007  NA          0    NA    NA   NA       NA    NA
-#> 10 SLOBER.1007  NA          0    NA    NA   NA       NA    NA
-#> # ... with 26,197 more rows
-
-
-

Exploring the distribution of status and tree diameter

-

Two columns that are commonly useful in ForestGEO datasets are status and dbh (diameter at breast height). We will begin by better understanding what type of variables they are. For this, base R provides useful functions.

-

status is a categorical variable.

-
summary(stem6$status)
-#>    Length     Class      Mode 
-#>        30 character character
-

We can count the number of observations in each category with table(), then visualize the result with barplot().

-
by_category <- table(stem6$status)
-barplot(by_category)
-

-

dbh is a continuous numeric variable.

-
summary(stem6$dbh)
-#>    Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's 
-#>   10.50   33.25  127.50  143.63  188.00  528.00       8
-

(Note the missing values (NAs).)

-

And we can visualize its distribution with hist().

-
hist(stem6$dbh)
-

-

Unfortunately hist() dropped missing values silently. But we can better understand how missing values of dbh relate to status by extracting only the columns dbh and status, and picking only the rows where dbh is missing.

-
dbh_status <- stem6[c("dbh", "status")]
-missing <- filter(dbh_status, is.na(dbh))
-unique(missing)
-#> # A tibble: 2 x 2
-#>     dbh status
-#>   <dbl> <chr> 
-#> 1    NA D     
-#> 2    NA G
-

Another approach is to count missing values.

-
missing <- transform(stem6, na = ifelse(is.na(dbh), TRUE, FALSE))
-table(missing$na, missing$status)
-#>        
-#>          A  D  G
-#>   FALSE 22  0  0
-#>   TRUE   0  4  4
-

We learn that dbh is missing where a tree is dead (status = D) or gone (status = G). This makes sense and, depending on the type of analysis we want to do, we may want to keep or remove missing values.

-
-
-

Determining tree status based on stem status

-

Now we are ready to clean the data. For example, we can pick trees which status is “A” (alive). At ForestGEO, working with status is so common that fgeo provides a specialized function.

-
fgeo_help("status")
-

In stem6, the variable status records the status of each individual stem. How can we determine the status of a tree based on the status of each of its stems? That is the job of add_status_tree().

-
stem6 <- add_status_tree(stem6, status_a = "A", status_d = "D")
-alive_trees <- filter(stem6, status_tree == "A")
-
-# Note that alive trees may have some missing, gone or dead stems
-some_cols <- c( "treeID", "status_tree", "stemID", "status")
-example_tree <- 46
-example_rows <- filter(alive_trees, treeID == example_tree)
-select(example_rows, some_cols)
-#> # A tibble: 0 x 4
-#> # ... with 4 variables: treeID <int>, status_tree <chr>, stemID <int>,
-#> #   status <chr>
-
-
-

Picking a dbh range

-

Another very common task when working with ForestGEO data is to pick stems of a particular dbh range.

-
fgeo_help("dbh")
-

Pick stems of 10 mm or more.

-
ten_plus <- pick_dbh_min(alive_trees, 10)
-range(ten_plus$dbh, na.rm = TRUE)
-#> [1]  10.5 528.0
-
-
-

Calculating abundance

-

Calculate the total abundance of stems and trees.

-
# Drop missing values of `dbh`
-non_missing <- filter(ten_plus, !is.na(dbh))
-
-# Stem abundance
-abundance(non_missing)
-#> # A tibble: 1 x 1
-#>       n
-#>   <int>
-#> 1    22
-
-# Tree abundance (picking main stems -- with highest `hom` and largest `dbh`)
-main_stems <- pick_main_stem(non_missing)
-abundance(main_stems)
-#> # A tibble: 1 x 1
-#>       n
-#>   <int>
-#> 1    22
-

Calculate the abundance of trees by species.

-
by_sp <- group_by(main_stems, sp)
-n_by_sp <- abundance(by_sp)
-n_by_sp
-#> # A tibble: 13 x 2
-#> # Groups:   sp [13]
-#>    sp         n
-#>    <chr>  <int>
-#>  1 CASARB     1
-#>  2 CECSCH     1
-#>  3 CORSUL     1
-#>  4 DACEXC     2
-#>  5 GUTCAR     1
-#>  6 HIRRUG     1
-#>  7 INGLAU     2
-#>  8 IXOFER     1
-#>  9 MANBID     3
-#> 10 MATDOM     1
-#> 11 PREMON     6
-#> 12 PSYBER     1
-#> 13 SLOBER     1
-
-
-

Picking the most abundant species

-

What are the three most abundant tree species?

-
(top3_species <- arrange(n_by_sp, desc(n))[["sp"]][1:3])
-#> [1] "PREMON" "MANBID" "DACEXC"
-

Now we can pick the alive_trees of only the top3 species.

-
picked_stems <- filter(alive_trees, sp %in% top3_species)
-
-
-

Mapping the distribution of tree species

-

fgeo includes some functions specialized in mapping ForestGEO’s data.

-
fgeo_help("map")
-

Map the most abundant species.

-
example_elevation <- fgeo.x::elevation
-
-species_elevation <- sp_elev(picked_stems, example_elevation)
-autoplot(species_elevation)
-

-

Tweak to focus on the hectare available in the data.

-
autoplot(species_elevation, xlim = c(100, 200), ylim = c(400, 500))
-

-
-
-

Species-habitat associations

-
tree <- download_data("luquillo_tree5_random")
-elevation <- download_data("luquillo_elevation")
-
-# Pick alive trees, of 10 mm or more
-census <- filter(tree, status == "A", dbh >= 10)
-
-# Pick sufficiently abundant species
-pick <- filter(add_count(census, sp), n > 50)
-species <- unique(pick$sp)
-
-# Use your habitat data or create it from elevation data
-habitat <- fgeo_habitat(elevation, gridsize = 20, n = 4)
-
-# A list or matrices
-tt_lst <- tt_test(census, species, habitat)
-#> Using `plotdim = c(320, 500)`. To change this value see `?tt_test()`.
-#> Using `gridsize = 20`. To change this value see `?tt_test()`.
-tt_lst
-#> [[1]]
-#>        N.Hab.1 Gr.Hab.1 Ls.Hab.1 Eq.Hab.1 Rep.Agg.Neut.1 Obs.Quantile.1
-#> CASARB      35     1508       90        2              0         0.9425
-#>        N.Hab.2 Gr.Hab.2 Ls.Hab.2 Eq.Hab.2 Rep.Agg.Neut.2 Obs.Quantile.2
-#> CASARB      24      433     1162        5              0       0.270625
-#>        N.Hab.3 Gr.Hab.3 Ls.Hab.3 Eq.Hab.3 Rep.Agg.Neut.3 Obs.Quantile.3
-#> CASARB      11      440     1157        3              0          0.275
-#>        N.Hab.4 Gr.Hab.4 Ls.Hab.4 Eq.Hab.4 Rep.Agg.Neut.4 Obs.Quantile.4
-#> CASARB       8      774      824        2              0        0.48375
-#> 
-#> [[2]]
-#>        N.Hab.1 Gr.Hab.1 Ls.Hab.1 Eq.Hab.1 Rep.Agg.Neut.1 Obs.Quantile.1
-#> PREMON      94     1511       87        2              0       0.944375
-#>        N.Hab.2 Gr.Hab.2 Ls.Hab.2 Eq.Hab.2 Rep.Agg.Neut.2 Obs.Quantile.2
-#> PREMON      97     1403      196        1              0       0.876875
-#>        N.Hab.3 Gr.Hab.3 Ls.Hab.3 Eq.Hab.3 Rep.Agg.Neut.3 Obs.Quantile.3
-#> PREMON      39      212     1386        2              0         0.1325
-#>        N.Hab.4 Gr.Hab.4 Ls.Hab.4 Eq.Hab.4 Rep.Agg.Neut.4 Obs.Quantile.4
-#> PREMON      15       64     1535        1              0           0.04
-#> 
-#> [[3]]
-#>        N.Hab.1 Gr.Hab.1 Ls.Hab.1 Eq.Hab.1 Rep.Agg.Neut.1 Obs.Quantile.1
-#> SLOBER      21      413     1183        4              0       0.258125
-#>        N.Hab.2 Gr.Hab.2 Ls.Hab.2 Eq.Hab.2 Rep.Agg.Neut.2 Obs.Quantile.2
-#> SLOBER      25      558     1040        2              0        0.34875
-#>        N.Hab.3 Gr.Hab.3 Ls.Hab.3 Eq.Hab.3 Rep.Agg.Neut.3 Obs.Quantile.3
-#> SLOBER      21     1289      309        2              0       0.805625
-#>        N.Hab.4 Gr.Hab.4 Ls.Hab.4 Eq.Hab.4 Rep.Agg.Neut.4 Obs.Quantile.4
-#> SLOBER       8      833      764        3              0       0.520625
-
-# A simple summary to help you interpret the results
-summary(tt_lst)
-#>   Species Habitat_1 Habitat_2 Habitat_3 Habitat_4
-#> 1  CASARB   neutral   neutral   neutral   neutral
-#> 2  PREMON   neutral   neutral   neutral   neutral
-#> 3  SLOBER   neutral   neutral   neutral   neutral
-
-# A combined matrix
-Reduce(rbind, tt_lst)
-#>        N.Hab.1 Gr.Hab.1 Ls.Hab.1 Eq.Hab.1 Rep.Agg.Neut.1 Obs.Quantile.1
-#> CASARB      35     1508       90        2              0       0.942500
-#> PREMON      94     1511       87        2              0       0.944375
-#> SLOBER      21      413     1183        4              0       0.258125
-#>        N.Hab.2 Gr.Hab.2 Ls.Hab.2 Eq.Hab.2 Rep.Agg.Neut.2 Obs.Quantile.2
-#> CASARB      24      433     1162        5              0       0.270625
-#> PREMON      97     1403      196        1              0       0.876875
-#> SLOBER      25      558     1040        2              0       0.348750
-#>        N.Hab.3 Gr.Hab.3 Ls.Hab.3 Eq.Hab.3 Rep.Agg.Neut.3 Obs.Quantile.3
-#> CASARB      11      440     1157        3              0       0.275000
-#> PREMON      39      212     1386        2              0       0.132500
-#> SLOBER      21     1289      309        2              0       0.805625
-#>        N.Hab.4 Gr.Hab.4 Ls.Hab.4 Eq.Hab.4 Rep.Agg.Neut.4 Obs.Quantile.4
-#> CASARB       8      774      824        2              0       0.483750
-#> PREMON      15       64     1535        1              0       0.040000
-#> SLOBER       8      833      764        3              0       0.520625
-
-# A dataframe
-to_df(tt_lst)
-#> # A tibble: 12 x 8
-#>    habitat sp     N.Hab Gr.Hab Ls.Hab Eq.Hab Rep.Agg.Neut Obs.Quantile
-#>  * <chr>   <chr>  <dbl>  <dbl>  <dbl>  <dbl>        <dbl>        <dbl>
-#>  1 1       CASARB    35   1508     90      2            0        0.942
-#>  2 2       CASARB    24    433   1162      5            0        0.271
-#>  3 3       CASARB    11    440   1157      3            0        0.275
-#>  4 4       CASARB     8    774    824      2            0        0.484
-#>  5 1       PREMON    94   1511     87      2            0        0.944
-#>  6 2       PREMON    97   1403    196      1            0        0.877
-#>  7 3       PREMON    39    212   1386      2            0        0.132
-#>  8 4       PREMON    15     64   1535      1            0        0.04 
-#>  9 1       SLOBER    21    413   1183      4            0        0.258
-#> 10 2       SLOBER    25    558   1040      2            0        0.349
-#> 11 3       SLOBER    21   1289    309      2            0        0.806
-#> 12 4       SLOBER     8    833    764      3            0        0.521
-
- - - - - - - -