Stand and Stock Table Workflows with Tidyverse

FOR 372

Elliot Shannon

2025-03-25

Goals

  • Use tidyverse workflows to build stand and stock tables.

  • Leverage group_by() grouping methods to compute estimates for populations of interest.

  • Understand complete() and pivot_wider() functions.

Example Stand-Level Estimates

Estimates for number of trees and wood volume per acre by species.
Species DBH (in) Trees/ac Volume (ft3/ac)
Abies balsamea 11.3 8 142.8
Betula papyrifera 14.8 8 269.6
Betula papyrifera 15.4 8 293.7
Pinus strobus 9.8 8 116.3
Pinus strobus 10.7 8 143.6
Pinus strobus 13.1 8 231.9

Stand tables summarize a quantitative discrete variable (e.g., stem count) grouped by one or more categorical (i.e., qualitative) variable (e.g., size class or species).

DBH Classes (in)
Species [6,10] (10,14] (14, 18] Totals
Abies balsamea 0 8 0 8
Betula papyrifera 0 0 16 16
Pinus strobus 8 16 0 24
Totals 8 24 16 48

Values are numbers of trees per acre.

Stock tables summarize a quantitative continuous variable (e.g., volume, weight, or basal area) grouped by one or more categorical variable.

DBH Classes (in)
Species [6,10] (10,14] (14, 18] Totals
Abies balsamea 0 142.8 0 142.8
Betula papyrifera 0 0 563.3 563.3
Pinus strobus 116.3 375.5 0 491.8
Totals 116.3 518.3 563.3 1197.9

Values are volume cubic feet per acre.

Each row and column combination in the table defines a unique population.

DBH Classes (in)
Species [6,10] (10,14] (14, 18]
Abies balsamea Pop 1 Pop 2 Pop 3
Betula papyrifera Pop 4 Pop 5 Pop 6
Pinus strobus Pop 7 Pop 8 Pop 9

Our task is to generate an estimate for each population.

Recall this example population

We take a sample

# Read in the stand data
stands <- read_csv("two_stands.csv")

# Filter only Stand 1 Overstory trees
# Select columns needed to build the stand and stock tables
o_stand <- stands %>% 
  filter(stand_id == 1, tree_type == "Overstory") %>%
  select(plot_id, tree_count, scientific_name, DBH_in, vol_cu_ft)

o_stand
# A tibble: 7 × 5
  plot_id tree_count scientific_name   DBH_in vol_cu_ft
    <dbl>      <dbl> <chr>              <dbl>     <dbl>
1       1          1 Abies balsamea      11.3      17.8
2       1          1 Pinus strobus        9.8      14.5
3       1          1 Pinus strobus       10.7      17.9
4       2          0 <NA>                 0         0  
5       3          1 Betula papyrifera   14.8      33.6
6       3          1 Betula papyrifera   15.4      36.6
7       3          1 Pinus strobus       13.1      28.9

Since there were no trees on Plot 2 in Stand 1, we preserve that zero count using the tree_count variable.

# A tibble: 7 × 5
  plot_id tree_count scientific_name   DBH_in vol_cu_ft
    <dbl>      <dbl> <chr>              <dbl>     <dbl>
1       1          1 Abies balsamea      11.3      17.8
2       1          1 Pinus strobus        9.8      14.5
3       1          1 Pinus strobus       10.7      17.9
4       2          0 <NA>                 0         0  
5       3          1 Betula papyrifera   14.8      33.6
6       3          1 Betula papyrifera   15.4      36.6
7       3          1 Pinus strobus       13.1      28.9

Why save this zero value?

A plot with no trees is part of the sample, reflects a characteristic of the population, and hence needs to be included as a zero when computing population parameter estimates.