Convert volume to aboveground biomass components (Boudewyn et al. 2007)
V2B.RdHigh-level wrapper for the Boudewyn et al. (2007) model-based volume-to-biomass conversion for live trees. Given gross merchantable volume per hectare, the function:
converts volume to stem wood biomass components (Tables 3–5; Eqs. 1–3),
computes biomass proportions using the volume-based multinomial-logit models (Table 6; Eqs. 4–7),
applies the Table 7 proportion bounds (caps) to prevent unrealistic proportions when extrapolating,
returns total aboveground biomass and components (bark, branches, foliage).
Usage
v2b(
vol_merchantable,
species,
jurisdiction,
ecozone,
include_props = FALSE,
include_intermediates = FALSE,
renormalize = TRUE,
clamp_x = FALSE
)Arguments
- vol_merchantable
Numeric vector. Gross merchantable volume per hectare.
- species
Character vector. NFI species codes (e.g.,
"PICE.MAR"). Genus-level codes ("PICE.SPP") and variety-level codes ("PICE.MAR.AAA") are supported.- jurisdiction
Character vector. Jurisdiction code (e.g.,
"AB").- ecozone
Ecozone identifier. Either: numeric ecozone code (1–15) or official ecozone name (English or French; case-insensitive).
- include_props
Logical. If TRUE, include biomass proportions (
p_sw,p_sb,p_br,p_fl) in the output.- include_intermediates
Logical. If TRUE, include intermediate stem-biomass quantities (
b_m,b_n,b_nm,b_s) and factors (f_nm,f_s,has_sapling,b_stem_total).- renormalize
Logical. If TRUE (default), renormalize capped proportions to sum to 1. This can be helpful when multiple components hit bounds.
- clamp_x
Logical. If TRUE, clamp
vol_merchantableto the calibration range[x_min, x_max]from Table 7 before evaluating the proportion equations. Disabled by default.
Value
A tibble with one row per input observation. By default includes:
- b_total
Total aboveground tree biomass (t/ha).
- b_bark
Bark biomass (t/ha).
- b_branches
Branch biomass (t/ha).
- b_foliage
Foliage biomass (t/ha).
Additional columns are included when include_props and/or
include_intermediates are TRUE.
Details
The function is vectorized over all inputs and is designed to work naturally
inside dplyr::mutate() (typically followed by tidyr::unnest()).
Proportion caps (Table 7). The Table 6 proportion models can yield extreme values when extrapolated beyond the calibration range. This implementation applies Table 7 bounds (low/high caps) to each proportion to keep outputs within plausible limits.
Extrapolation vs clamping.
By default (clamp_x = FALSE), the input vol_merchantable is used directly.
If vol_merchantable falls outside the calibration range (x_min/x_max) reported
in Table 7, results are extrapolations, although Table 7 proportion caps are still
applied. Setting clamp_x = TRUE replaces vol_merchantable with
min(max(vol_merchantable, x_min), x_max) before computing proportions; this can
materially change results for high-volume stands and may lead to systematic
underestimation where vol_merchantable > x_max. For this reason, clamping is disabled
by default.
Examples
# Single case (one stand)
v2b(
vol_merchantable = 350,
species = "PSEU.MEN",
jurisdiction = "BC",
ecozone = 13
)
#> # A tibble: 1 × 4
#> b_total b_bark b_branches b_foliage
#> <dbl> <dbl> <dbl> <dbl>
#> 1 241. 33.2 24.0 6.03
# Include proportions and intermediate quantities used in the calculation
v2b(
vol_merchantable = 350,
species = "PSEU.MEN",
jurisdiction = "BC",
ecozone = 13,
include_props = TRUE,
include_intermediates = TRUE
)
#> # A tibble: 1 × 16
#> b_total b_bark b_branches b_foliage p_sw p_sb p_br p_fl b_m b_n
#> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 241. 33.2 24.0 6.03 0.738 0.138 0.0995 0.0250 153. 24.7
#> # ℹ 6 more variables: b_nm <dbl>, b_s <dbl>, f_nm <dbl>, f_s <dbl>,
#> # has_sapling <lgl>, b_stem_total <dbl>
# Tidyverse workflow: compute biomass for multiple stands
# (one row per stand) and bind results as new columns.
library(dplyr)
#>
#> Attaching package: ‘dplyr’
#> The following objects are masked from ‘package:stats’:
#>
#> filter, lag
#> The following objects are masked from ‘package:base’:
#>
#> intersect, setdiff, setequal, union
library(tidyr)
stands <- tibble::tibble(
stand_id = 1:3,
vol_merchantable = c(120, 350, 300),
species = c("PICE.MAR", "PSEU.MEN", "PINU.BAN"),
jurisdiction = c("AB", "BC", "ON"),
ecozone = c(5, 13, 6)
)
stands |>
mutate(
v2b = v2b(
vol_merchantable = vol_merchantable,
species = species,
jurisdiction = jurisdiction,
ecozone = ecozone,
include_props = TRUE
)
) |>
unnest(v2b)
#> # A tibble: 3 × 13
#> stand_id vol_merchantable species jurisdiction ecozone b_total b_bark
#> <int> <dbl> <chr> <chr> <dbl> <dbl> <dbl>
#> 1 1 120 PICE.MAR AB 5 136. 13.6
#> 2 2 350 PSEU.MEN BC 13 241. 33.2
#> 3 3 300 PINU.BAN ON 6 176. 13.5
#> # ℹ 6 more variables: b_branches <dbl>, b_foliage <dbl>, p_sw <dbl>,
#> # p_sb <dbl>, p_br <dbl>, p_fl <dbl>