Objective

To analyse the competition between trees, forest inventory requires information on tree position. When data are collected in broadleaved forests, a controversial topic is how to consider multi-stemmed trees, i.e. trees where the stump splits into two or more stems above ground level, a typical situation occurring in coppice woods.

A solution largely adopted in forest inventories is to assign the same coordinates to each shoot (or stool) of the same stump, e.g. by taking a mean position of the stump. However, such approach is not properly suitable when the objective is to understand the spatial relation between competing trees (e.g. species mingling). An alternative solution could be jittering the position of each shoot or stool from the ‘mean’ coordinate of the stump. However, even this solution is sub-optimal, in that the multi-stemmed tree should be considered a single entity competing with neighboring trees.

We suggest a different solution: for individuals shoots with identical coordinates calculate their cumulative basal area, and then kept only a “virtual individual” with single diameter and height attributes. We described in detail the procedure proposed with an example from mapped tree inventory data in an oak-hornbeam forest in Italy.

Dataset description

As case study, we use the dataset described in Fardusi et al. 2018, which is freely available at: https://data.mendeley.com/datasets/n8827ssnv7/2

Dataset contains replicated, repeated-measures data of diameter and height in three rectangular 70x140 m (~1 ha) oak-hoarnbeam plots sampled in Bosco Fontana National Reserve, Northern Italy. Inventories have been carried out in 1995, 2005 and 2016.

Data can be imported from the public repository URL in R. For the remainder of the analyses, we will consider only a subset of records and fields as following described.

datasetBF <- read.csv("https://data.mendeley.com/public-files/datasets/n8827ssnv7/files/656a2e78-aa9e-459a-b219-fe2627fcf9c8/file_downloaded") |> 
  as_tibble()


datasetBF <- datasetBF |> 
  dplyr::filter(VIT == 1) |> # filter only living trees
  dplyr::select(CA, inv_year, treeid, treeid_old, SP, BX, BY, DBH, TH)

datasetBF
## # A tibble: 4,449 × 9
##    CA    inv_year treeid treeid_old SP       BX    BY   DBH    TH
##    <chr>    <int>  <int> <chr>      <chr> <dbl> <dbl> <dbl> <dbl>
##  1 CA1       1995      5 1178       Cb      5.2   5.3    37    23
##  2 CA1       1995     11 1161       Cb      8.3   5      19    22
##  3 CA1       1995     21 1239       Ac      7.2  10.5     5     5
##  4 CA1       1995     23 1254       Cb      1    11.9    44    25
##  5 CA1       1995     24 1236       Ac      9.1  19.2     7     5
##  6 CA1       1995     34 1261       Fo      5.6  24      11    10
##  7 CA1       1995     37 1323       Cb      5.5  39.7    39    16
##  8 CA1       1995     40 1330       Fo      0.5  30.7    12     5
##  9 CA1       1995     44 1332       Pr      2    43       5     5
## 10 CA1       1995     45 1327       Pr      0.2  45.3     8     8
## # … with 4,439 more rows

where:

Dataset reshape

The original dataset, includes some coppice stools, which have identical tree coordinates.

datasetBF |> 
  group_by(CA, inv_year, BX, BY) |> 
  summarise(Ntrees = n()) |> 
  dplyr::filter(Ntrees > 1)
## # A tibble: 234 × 5
## # Groups:   CA, inv_year, BX [229]
##    CA    inv_year    BX    BY Ntrees
##    <chr>    <int> <dbl> <dbl>  <int>
##  1 CA1       1995  42.8  98.6      2
##  2 CA1       2005   3.6 128.       2
##  3 CA1       2005  10.9  87.5      2
##  4 CA1       2005  30.7  95        3
##  5 CA1       2005  31.3  96.8      2
##  6 CA1       2005  32.1 102.       2
##  7 CA1       2005  32.5  78.4      2
##  8 CA1       2005  37.4  60.7      6
##  9 CA1       2005  38.1  97.3      2
## 10 CA1       2005  38.2  90.5      5
## # … with 224 more rows

For individuals with identical coordinates, we suggest to calculate their cumulative basal area, and then kept only a “virtual individual”, whose:

We illustrated the example with one tree (treeid_old = 176) sampled in CA1 in 2016, with 8 individuals with same coordinates.

# Look for the specific case
datasetBF |> 
  group_by(CA, inv_year, BX, BY) |> 
  mutate(Ntrees = n()) |> 
  dplyr::filter(CA == "CA1",
                inv_year == 2016,
                Ntrees == 8)
## # A tibble: 8 × 10
## # Groups:   CA, inv_year, BX, BY [1]
##   CA    inv_year treeid treeid_old SP       BX    BY   DBH    TH Ntrees
##   <chr>    <int>  <int> <chr>      <chr> <dbl> <dbl> <dbl> <dbl>  <int>
## 1 CA1       2016     50 176-a      Ca        2  48.8     9    11      8
## 2 CA1       2016     51 176-b      Ca        2  48.8     7    11      8
## 3 CA1       2016     52 176-c      Ca        2  48.8     8    11      8
## 4 CA1       2016     53 176-d      Ca        2  48.8     7    11      8
## 5 CA1       2016     54 176-e      Ca        2  48.8     8    11      8
## 6 CA1       2016     55 176-f      Ca        2  48.8     8    11      8
## 7 CA1       2016     56 176-g      Ca        2  48.8     7    11      8
## 8 CA1       2016     57 176-h      Ca        2  48.8     8    11      8
# Isolate the case
# CA1-2016. The old tree.id are 176 and 477

dBF.CA1.2016.176 <- datasetBF |> 
  dplyr::filter(CA == "CA1",
                inv_year == 2016,
                BX == 2, BY == 48.8) 

The red point is the tree position (BX, BY) recorded in the dataset for all the individuals belonging to tree.id 176. In the figure, a small amount of random variation to the original position of the 8 individuals was added using geom_jitter. When applying the approach proposed, the 8 individuals conveys in a single individual with the following attributes:

## # A tibble: 1 × 9
## # Groups:   CA, inv_year, SP, BX, BY [1]
##   CA    inv_year SP       BX    BY n_shoots avg_ba    TH avg_dbh
##   <chr>    <int> <chr> <dbl> <dbl>    <dbl>  <dbl> <dbl>   <dbl>
## 1 CA1       2016 Ca        2  48.8        8   47.5    11    7.78

Now we can map the procedure to the entire datasetBF and create a new dataset bfontana, which can be used for further analysis. The code needed is the following:

bfontana <- datasetBF |> 
  dplyr::mutate(ba_j.cm = pi*(DBH/2)^2) |> 
  group_by(CA, inv_year, SP, BX, BY) |> 
  nest() |> 
  dplyr::mutate(n_shoots = map_dbl(data, ~{length(.x$ba_j.cm)}),
                avg_ba = map_dbl(data, ~{mean(.x$ba_j.cm)}),
                TH = map_dbl(data, ~{max(.x$TH)})) |> 
  dplyr::mutate(avg_dbh = 2*sqrt(avg_ba/pi)) |> 
  dplyr::select(-data)

bfontana
## # A tibble: 4,061 × 9
## # Groups:   CA, inv_year, SP, BX, BY [4,061]
##    CA    inv_year SP       BX    BY n_shoots avg_ba    TH avg_dbh
##    <chr>    <int> <chr> <dbl> <dbl>    <dbl>  <dbl> <dbl>   <dbl>
##  1 CA1       1995 Cb      5.2   5.3        1 1075.     23      37
##  2 CA1       1995 Cb      8.3   5          1  284.     22      19
##  3 CA1       1995 Ac      7.2  10.5        1   19.6     5       5
##  4 CA1       1995 Cb      1    11.9        1 1521.     25      44
##  5 CA1       1995 Ac      9.1  19.2        1   38.5     5       7
##  6 CA1       1995 Fo      5.6  24          1   95.0    10      11
##  7 CA1       1995 Cb      5.5  39.7        1 1195.     16      39
##  8 CA1       1995 Fo      0.5  30.7        1  113.      5      12
##  9 CA1       1995 Pr      2    43          1   19.6     5       5
## 10 CA1       1995 Pr      0.2  45.3        1   50.3     8       8
## # … with 4,051 more rows

References

Pommerening, A., Stoyan, D. (2006). Edge-correction needs in estimating indices of spatial forest structure. Canadian Journal of Forest Research, 36, 7, pag. 1723-1739. https://doi.org/10.1139/X06-060

Fardusi, M.J., Castaldi, C., Chianucci, F. et al. (2018). A spatio-temporal dataset of forest mensuration for the analysis of tree species structure and diversity in semi-natural mixed floodplain forests. Annals of Forest Science 75, 11. https://doi.org/10.1007/s13595-018-0688-8