This vignette describes a series of functions in the forestexplorR package that provide quantitative descriptions of local neighborhoods in mapped forest stands. The neighborhood of a specific location in a mapped stand is the collection of trees growing within a specified distance of that location.
Of these functions, neighborhoods()
constructs the list of all trees in each neighborhood. neighborhood_summary()
takes the output of neighborhoods()
as input and calculates tree species richness and species-specific densities for each neighborhood. site_by_species()
also takes the output of neighborhoods()
as input but creates a site-by-species matrix, where each site is a different neighborhood, that can be used to calculate diversity metrics. tree_utm()
takes a mapping object as input and calculates UTM coordinates for each tree, thereby allowing trees to be linked to fine-scale spatial data such as topography.
neighborhoods()
: Construct neighborhoodsThe neighborhoods()
function uses a mapping dataset to determine, for each tree, all the trees that are within a certain distance (radius
). The argument stand
can be used to indicate that neighborhoods should be constructed only for the trees of one or more of the stands included in mapping
. If stand
is not specified, neighborhoods will be constructed for all trees in mapping
.
The output is a data frame where each row contains information on a focal tree and one other tree growing in the focal tree’s neighborhood. Therefore, the information for each focal tree will appear on x lines, where x is the number of trees in that focal tree’s neighborhood. This structure is shown below by isolating a single focal tree in the output of applying neighborhoods()
to the built-in mapping
dataset:
nbhds <- neighborhoods(mapping, stand = "AB08", radius = 10)
nbhds %>%
filter(tree_id == "AB08000100022")
#> tree_id stand_id species dbh abh x_coord y_coord id_comp
#> 1 AB08000100022 AB08 TSHE 15.1 179.0786 18.11 95.68 AB08000100001
#> 2 AB08000100022 AB08 TSHE 15.1 179.0786 18.11 95.68 AB08000100002
#> 3 AB08000100022 AB08 TSHE 15.1 179.0786 18.11 95.68 AB08000100003
#> 4 AB08000100022 AB08 TSHE 15.1 179.0786 18.11 95.68 AB08000100004
#> 5 AB08000100022 AB08 TSHE 15.1 179.0786 18.11 95.68 AB08000100005
#> 6 AB08000100022 AB08 TSHE 15.1 179.0786 18.11 95.68 AB08000100007
#> 7 AB08000100022 AB08 TSHE 15.1 179.0786 18.11 95.68 AB08000100017
#> prox sps_comp dbh_comp abh_comp
#> 1 6.423161 TSHE 50.4 1995.0370
#> 2 6.079679 TSHE 81.1 5165.7287
#> 3 4.925627 TSHE 20.0 314.1593
#> 4 5.221571 TSHE 53.7 2264.8448
#> 5 7.283028 TSHE 24.4 467.5947
#> 6 7.504265 THPL 57.0 2551.7586
#> 7 6.124255 TSHE 24.6 475.2916
The neighborhoods()
function can also be used to construct neighborhoods for specific coordinates within the mapped stand instead of constructing a neighborhood centered on each tree in the dataset. This is achieved by providing a data frame of coordinates under the optional argument coords
(see neighborhoods()
documentation for details on how this data frame should be structured).
# Create a data frame of coordinates
locations <- data.frame(
loc_id = paste("A", 1:81, sep = ""),
x_coord = rep(seq(10, 90, 10), times = 9),
y_coord = rep(seq(10, 90, 10), each = 9))
# Construct neighborhood for each coordinate
coord_nbhds <- neighborhoods(mapping, stands = "AB08", radius = 10,
coords = locations)
head(coord_nbhds)
#> loc_id stand_id x_coord y_coord id_comp prox sps_comp dbh_comp
#> 1 A1 AB08 10 10 AB08001600008 6.144689 TSHE 20.2
#> 2 A1 AB08 10 10 AB08001600009 7.062294 TSHE 68.2
#> 3 A1 AB08 10 10 AB08001600010 9.539193 TSHE 55.4
#> 4 A1 AB08 10 10 AB08001600011 2.344462 TSHE 17.5
#> 5 A1 AB08 10 10 AB08001600012 2.979564 TSHE 59.7
#> 6 A1 AB08 10 10 AB08001600013 4.928539 PSME 72.5
#> abh_comp
#> 1 320.4739
#> 2 3653.0754
#> 3 2410.5126
#> 4 240.5282
#> 5 2799.2297
#> 6 4128.2491
neighborhood_summary()
: Summarize neighborhoodsThe neighborhood_summary()
function takes output of the neighborhoods()
function and calculates species diversity metrics, overall tree density, and densities of each tree species for each neighborhood. Diversity metrics include species richness, Shannon-Wiener diversity, Simpson’s diversity, and evenness (Pielou’s J).
The densities
argument is used to specify how densities should be calculated. The optimal method for density calculation is likely to vary between study systems and processes of interest. If the differential effects of neighbor tree species are likely to be influenced by how close the neighbors of each species are to the focal (e.g. when differences relate to competition for soil moisture or nutrients), the angular
method may be more appropriate. However, if the forest is in the vertical diversification stage of successional development, the influence of a large canopy-forming neighbor species may be relatively unaffected by whether neighbors of that species are 5m vs. 10m from the focal tree - in this case the raw
or proportional
measures may be more relevant.
There is also an option to correct the density values for neighborhoods that overlap the stand boundary. When edge_correction = T
, the density and species richness values for neighborhoods that overlap the stand boundary will be multiplied according to the proportion of their neighborhood that lies beyond the stand boundary (species richness values are rounded to the nearest whole number). See function documentation for details.
neighborhood_summary(densities = "raw")
Overall tree density and species-specific densities will be presented in units of \(m^{2}ha^{-1}\), with the area occupied by each tree calculated as the area of the trunk at breast height i.e. \[\pi(\frac{dbh}{2})^{2}\]
nbhd_summ <- neighborhood_summary(nbhds, id_column = "tree_id", radius = 10,
densities = "raw")
nbhd_summ %>%
select(tree_id, sps_richness, shannon, ABAM_density, TSHE_density, all_density)
#> # A tibble: 401 x 6
#> tree_id sps_richness shannon ABAM_density TSHE_density all_density
#> <chr> <int> <dbl> <dbl> <dbl> <dbl>
#> 1 AB08000100022 2 0.490 0 34.0 42.1
#> 2 AB08000100001 3 0.808 2.27 21.0 31.4
#> 3 AB08000100002 3 0.847 2.27 18.1 28.5
#> 4 AB08000100003 3 0.809 2.27 29.2 47.3
#> # ... with 397 more rows
neighborhood_summary(densities = "proportional")
Overall tree density is presented in units of \(m^{2}ha^{-1}\) but species-specific densities represent the proportion of overall tree density that each species accounts for.
nbhd_summ <- neighborhood_summary(nbhds, id_column = "tree_id", radius = 10,
densities = "proportional")
nbhd_summ %>%
select(tree_id, sps_richness, shannon, ABAM_density, TSHE_density, all_density)
#> # A tibble: 401 x 6
#> tree_id sps_richness shannon ABAM_density TSHE_density all_density
#> <chr> <int> <dbl> <dbl> <dbl> <dbl>
#> 1 AB08000100022 2 0.490 0 0.807 42.1
#> 2 AB08000100001 3 0.808 0.0721 0.669 31.4
#> 3 AB08000100002 3 0.847 0.0794 0.636 28.5
#> 4 AB08000100003 3 0.809 0.0479 0.618 47.3
#> # ... with 397 more rows
neighborhood_summary(densities = "angular")
Overall tree density and species-specific densities calculated as the sum of angles occupied by trees, where the angle occupied by a single tree is: \[arctan(\frac{dbh}{distance})\] In the above, dbh
is the dbh of the neighbor tree and distance
is the distance from the neighborhood center to the neighbor tree.
nbhd_summ <- neighborhood_summary(nbhds, id_column = "tree_id", radius = 10,
densities = "angular")
nbhd_summ %>%
select(tree_id, sps_richness, shannon, ABAM_angle_sum, TSHE_angle_sum,
all_angle_sum)
#> # A tibble: 401 x 6
#> tree_id sps_richness shannon ABAM_angle_sum TSHE_angle_sum all_angle_sum
#> <chr> <int> <dbl> <dbl> <dbl> <dbl>
#> 1 AB08000100022 2 0.490 0 0.428 0.503
#> 2 AB08000100001 3 0.808 0.0379 0.671 0.779
#> 3 AB08000100002 3 0.847 0.0323 0.530 0.626
#> 4 AB08000100003 3 0.809 0.0391 0.509 0.805
#> # ... with 397 more rows
neighborhood_summary(neighbors_incl = "larger_only")
It is also possible to restrict the diversity and density calculations to include only the neighbor trees that are larger than the focal. This may be useful if trees in the study system are expected to compete far less strongly with neighbors that are smaller than them.
nbhd_summ <- neighborhood_summary(nbhds, id_column = "tree_id", radius = 10,
densities = "angular",
neighbors_incl = "larger_only")
nbhd_summ %>%
select(tree_id, sps_richness, shannon, ABAM_angle_sum, TSHE_angle_sum,
all_angle_sum)
#> # A tibble: 364 x 6
#> tree_id sps_richness shannon ABAM_angle_sum TSHE_angle_sum all_angle_sum
#> <chr> <int> <dbl> <dbl> <dbl> <dbl>
#> 1 AB08000100022 2 0.490 0 0.428 0.503
#> 2 AB08000100001 2 0.635 0 0.535 0.606
#> 3 AB08000100003 3 0.813 0.0391 0.479 0.774
#> 4 AB08000100004 1 0 0 0.174 0.174
#> # ... with 360 more rows
site_by_species()
: Create site-by-species matricesThe site_by_species()
function takes output of the neighborhoods()
function and creates a site-by-species matrix where each site is a neighborhood. The resulting matrix can be used as input for functions in other packages (e.g. picante, vegan) that calculate various diversity metrics from site-by-species matrices.
The default is to present presence/absence data in the matrix:
ss_mat <- site_by_species(nbhds, id_column = "tree_id")
head(ss_mat)
#> ABAM ABPR CANO PSME TABR THPL TSHE
#> AB08000100022 0 0 0 0 0 1 1
#> AB08000100001 1 0 0 0 0 1 1
#> AB08000100002 1 0 0 0 0 1 1
#> AB08000100003 1 0 0 0 0 1 1
#> AB08000100004 0 0 0 0 0 0 1
#> AB08000100005 1 0 0 0 0 1 1
But if abundance = T
is specified, matrix element values will represent the number of trees of the associated species in the neighborhood:
ss_mat_abund <- site_by_species(nbhds, id_column = "tree_id", abundance = T)
head(ss_mat_abund)
#> ABAM ABPR CANO PSME TABR THPL TSHE
#> AB08000100022 0 0 0 0 0 1 6
#> AB08000100001 1 0 0 0 0 1 5
#> AB08000100002 1 0 0 0 0 1 6
#> AB08000100003 1 0 0 0 0 2 7
#> AB08000100004 0 0 0 0 0 0 3
#> AB08000100005 1 0 0 0 0 2 8
tree_utm()
: Calculate tree UTM coordinatesThe tree_utm()
function takes a mapping object as input and calculates UTM coordinates for each tree. The output spatial object can be used to extract further data for each tree from data sources with very high spatial resolution e.g. topography.
The required arguments for tree_utm()
are: geographic coordinates of the stands (stand_locs
), the ESPG code of the coordinate reference system of stand_locs
(original_crs
), and the ESPG code of the UTM zone in which the stands exist (utm_crs
).
The built-in stand_locations
dataset shows the expected structure of stand_locs
- see ?stand_locations
for details:
head(stand_locations)
#> stand_id y_azim latitude longitude
#> 1 TO04 12.58 46.74002 -121.8887
#> 2 TB13 90.99 46.74086 -121.8487
#> 3 AX15 298.32 46.74979 -121.8242
#> 4 AG05 84.42 46.74765 -121.8052
#> 5 AV06 45.74 46.77602 -121.7851
#> 6 AM16 58.80 46.76848 -121.7585
The output of tree_utm()
looks like the following:
mapping_utm <- tree_utm(mapping, stand_locations, 4326, 32610)
head(mapping_utm)
#> Simple feature collection with 6 features and 8 fields
#> Geometry type: POINT
#> Dimension: XY
#> Bounding box: xmin: 611415.1 ymin: 5197317 xmax: 611421.6 ymax: 5197329
#> Projected CRS: WGS 84 / UTM zone 10N
#> tree_id stand_id tag species year dbh x_coord y_coord
#> 1 AB08000100022 AB08 19 TSHE 2012 15.1 18.11 95.68
#> 2 AB08000100001 AB08 4001 TSHE 2012 50.4 11.78 96.77
#> 3 AB08000100002 AB08 4002 TSHE 2012 81.1 12.47 97.95
#> 4 AB08000100003 AB08 4003 TSHE 2012 20.0 14.94 91.91
#> 5 AB08000100004 AB08 4004 TSHE 2012 53.7 22.09 99.06
#> 6 AB08000100005 AB08 4005 TSHE 2012 24.4 12.16 91.48
#> geometry
#> 1 POINT (611417.2 5197322)
#> 2 POINT (611420.8 5197327)
#> 3 POINT (611421.6 5197326)
#> 4 POINT (611415.1 5197326)
#> 5 POINT (611418.6 5197317)
#> 6 POINT (611415.9 5197329)