21 Annualised Calculations
This target, aggregates the outputs of Chapter 20 to create project-wide emissions estimates on an annual basis with consideration of deductions due to deforestation (Chapter 16) and leakage (Chapter 19).
21.0.1 Baseline scenario emissions calculations
The first step is to calculate the net greenhouse gas emissions from the project area in the baseline scenario. The annualised calculations can differ for years years 1, 2-10, 11-20; and all years since the start of the project activity. Therefore, multiple estimates of the carbon stock changes for these time periods are required. Please note that, due to the adoption of a spatially explicit approach to modelling biomass and timber volume, the equations from the VM0010 methods have been modified and indeed simplified such that there is no need to generate strata for the project area.
The net change in carbon stock from wood products and logging slash across all parcels within the first year of harvest in the baseline (\(\Delta C_{NET\space{BSL(1)}}\)), in tonnes of carbon (\(tC\)), is calculated according to Eq. 23 of the VM0010 methods (Equation 21.1):
\[ \Delta C_{NET \space{BSL \space{t_{1}}}} = \sum_{i=1}^{P} A_{i\space{t}} \times \left(\frac{C_{DWSLASH \space{BSL}_{i\space{t}}}}{10} + C_{WP0 \space{BSL}_{i\space{t}}} + \frac{C_{WP100 \space {BSL}_{i\space{t}}}}{20} \right) \tag{21.1}\]
Where \(P\) is the number of parcels \(i\) in the project area; \(t\) is the number of years since harvest which, in this case, is 1; \(A\) is the area of the parcel \(i\) in hectares (\(ha\)), \(C_{DWSLASH \space{BSL}_i}\) is the carbon stock of dead wood from logging slash during timber harvest in the baseline scenario in the parcel \(i\) in tonnes of carbon per hectare (\(tC \space ha^{-1}\)), \(C_{WP0 \space{BSL}_i}\) is the carbon stock of wood products in the parcel \(i\), in \(tC \space ha^{-1}\), and \(C_{WP100 \space {BSL}_i}\) is the carbon stored in wood products in the parcel \(i\), in \(tC \space ha^{-1}\), that is assumed to be retired between 3-100 years after harvest.
Then, the net change in carbon stock from wood products and logging slash across all parcels for years \(t\) 2:10 since harvest in the baseline \(\Delta C_{NET \space{BSL \space{t_{2:10}}}}\) is calculated similarly according to Eq. 24 of the VM0010 methods (Equation 21.2):
\[ \Delta C_{NET \space{BSL \space{t_{2:10}}}} = \sum_{{i=1}}^{{P}} A_{i\space{t}} \times \left(\frac{C_{DWSLASH\space{BSL}_{i\space{t}}}}{10} + \frac{C_{WP100\space{BSL}_{i\space{t}}}}{20} \right) \tag{21.2}\]
Note that in Equation 21.2, the carbon stock of wood products for the start of the project is not included in this calculation as it concerns only additional carbon stock changes from the year 2 of the project activity.
The thrid component for calculating the net change in carbon stock from wood products is shown in Equation 21.3, in line with Eq. 25 of the VM0010 methods. Here, we calculate the net change in carbon stock across parcels for years \(t\) 11:20 since harvest in the baseline scenario, \(\Delta C_{NET \space{BSL \space{t_{11:20}}}}\):
\[ \Delta C_{NET \space{BSL \space{t_{11:20}}}} = \sum_{{i=1}}^{{P}} A_{i\space{t}} \times \frac{C_{WP100\space{BSL}_{i\space{t}}}}{20} \tag{21.3}\]
Here, only the carbon stock in wood products that is assumed to be retired between 3-100 years after harvest \(C_{WP100\space{BSL}_{i\space{t}}}\) is included in the calculation.
Equation 21.4 describes the calculation of the net change in carbon stock due to forest regrowth across all parcels in all years since harvest in the baseline scenario (in line with Eq. 26 of the VM0010 methods). Where \(t*\) is the elapsed time since the start of the project. Note that the regrowth rate differs according to the baseline parcel definition (either unplanted or planted). For \(i\) parcels designated as planted, regrowth (\(C_{RG \space{BSL}_{i\space{t*}}}\)) was 3 \(Mg\space{C\space{ha^{-1} yr{-1}}}\) and for \(i\) parcels designated as unplanted, the growth rate was 1.6 \(Mg\space{C\space{ha^{-1} yr{-1}}}\) as derived in Chapter 15 .
\[ \Delta C_{NET\space{BSL}\space{(1+)}} = \sum_{{i=1}}^{{P}} A_{i\space{t*}} \times C_{RG \space{BSL}_{i\space{t*}}} \tag{21.4}\]
The resulting values from Equation 21.1, Equation 21.2, Equation 21.3 and Equation 21.4 are then summed alongside the Total carbon emissions associated with the combustion of fossil fuel in forestry and wood processing machinery, in \(tC\), in line with Eq. 27 of the VM0010 methods, to calculate net change in carbon stock across all parcels and years in the baseline scenario (\(\Delta C_{NET\space{BSL}_t*}\)):
\[ \begin{aligned} \Delta C_{NET\space{BSL}_t*} = \sum_{{i=1}}^{{P}} \biggl(& -\Delta C_{NET\space{BSL\space{t_{1}}}} \\ & \quad - \Delta C_{NET\space{BSL\space{t_{2:10}}}} \\ & \quad - \Delta C_{NET\space{BSL\space{t_{11:20}}}} \\ & \quad + \Delta C_{NET\space{BSL}\space{(1+)}} \biggr) \end{aligned} \tag{21.5}\]
Next, the net carbon stock change (\(GHG_{NET\space{BSL_{t*}}}\)) in the baseline scenario was converted to net greenhouse gas emissions and is calculated as in Eq. 28 of the VM0010 methods, according to Equation 21.6:
\[ GHG_{NET\space{BSL_{t*}}} = \Delta C_{NET\space{BSL}_t*} \times \frac{44}{12} \tag{21.6}\]
21.0.2 Project scenario emissions calculations
The annual change in carbon stock in above ground biomass (\(\Delta C_{AB\space{PRJ}_t}\)) is described in Eq. 32 of the VM0010 methods (v1.4).
Monitoring report (MR) 1 was verified under VM0010 v1.3. At this time, Permian Global adopted a more conservative equation than presented in Eq. 32 (v1.3). To avoid any risk of accounting for on-going forest growth, prior to the parcel harvest date in the baseline, we reformulated this equation, as presented in Equation 21.7, so that only areas of the project that would have been harvested prior to the close of the monitoring period were considered.
Equation 21.7 iterates at the parcel (\(P_i\)) level rather than strata level. All parcels, considered in this project, comprise a single strata and corresponding project growth rate (\(GR_{i\space{t}}\)) as derived in Chapter 17 . Therefore, for each parcel \(i\) the annual growth rate is calculated as the product of the area of the parcel (\(A_{i}\)), the growth rate (\(GR_{i\space{t}}\)) and the conversion factor from carbon to CO2 (\(44/12\)).
Ongoing forest growth is only applied on or after the baseline harvest date of the parcel (\(t_{p \space{harv} \space{BSL}}\)). When year \(t\) is less than the baseline harvest date, the on-going forest growth is zero. When year \(t\) is greater than the baseline harvest date, only the growth in that year is considered. For MR1 (and not after 2021), when year \(t\) is equal to the baseline harvest date, the on-going forest growth is equal to the years since the start of the project multiplied by the growth rate, to account for growth prior to harvest.
Since the publication of VM0010 v1.4, we have included a condition to account for the difference in methodological treatment during MR1 and thereafter (> 2021). In this case, where the scaling condition is equal to 1, Equation 21.7 is equivalent to the updated forumlation of Eq. 32 (v1.4).
\[ \Delta C_{AB\space{PRJ}_t} = \sum_{{i=1}}^{{P}} \left ( A_{i} \times GR_{i\space{t}} \times \frac{44}{12} \times \begin{cases} 0, \space \space \text {if } \space t < t_{p \space{harv} \space{BSL}} \\ 1, \space \space \text {if } \space t_{p \space{harv} \space{BSL}} > 2021 \\ 1 + t - t_{proj \space{start}}, \space \space \text {if } \space t = t_{p \space{harv} \space{BSL}} \\ 1, \space \space \text {if } \space t > t_{p \space{harv} \space{BSL}} \end{cases} \right) \tag{21.7}\]
Then, the net greenhouse gas emissions in the project scenario (\(\Delta C_{NET\space{PRJ}}\)) in year \(t\), in \(tCO2e\) is calculated as in Eq. 38 of the VM0010 methods and shown in Equation 21.8.
\[ \begin{aligned} \Delta C_{NET\space{PRJ}_t*} = \Delta C_{AB,\space{PRJ}_t*} - \biggl( & \Delta C_{DISTfire\space{PRJ}_t*} \\ & \quad + \Delta C_{DIST\space{PRJ}_t*} \\ & \quad + \Delta C_{DISTill\space{PRJ}_t*} \biggr) \end{aligned} \tag{21.8}\]
Where \(\Delta C_{DISTfire\space{PRJ}_t*}\) is the net change in carbon stock due to disturbance by fire in the project scenario in year \(t\), in \(tCO2e\); \(\Delta C_{DIST\space{PRJ}_t*}\) is the net change in carbon stock due to non-fire natural disturbance in the project scenario in year \(t\), in \(tCO2e\); \(\Delta C_{DISTill\space{PRJ}_t*}\) is the net change in carbon stock due to illegal logging in the project scenario in year \(t\), in \(tCO2e\); and \(\Delta C_{AB,\space{PRJ}_t*}\) is the annual change in carbon stock as calculated in Equation 21.7.
The net greenhouse gas emissions, across in the project scenario since the start of the project, (\(GHG_{NET\space{PRJ}}\)) is calculated as in Eq. 39 of the VM0010 methods and shown in Equation 21.9:
\[ GHG_{NET\space{PRJ}} = \sum_{t=1}^{t*} \Delta C_{NET\space{PRJ}_t} \tag{21.9}\]
21.0.3 Calculation of net GHG emission reductions, removals and Verified Carbon Units
In the VM0010 method v1.4, the calculation of net GHG emission reductions has been updated to enable the separation of emission reductions and removals. These equations are set out as follows:
21.0.3.1 Net reductions and removals
In Equation 21.10 (Eq. 40 of the VM0010 methods) Net GHG emission reductions in year t* since the start of the project activity, in the project scenario (\(ER_t\)) is calculated as the sum of the difference between the carbon stock changes in the baseline and project scenarios. If the net carbon stock change in the baseline scenario (\(\Delta C_{NET\space{BSL_{t*}}}\)) is positive, indicating there would have been net sequestration, then no emission reductions are calculated. Likewise, if the net carbon stock change in the project scenario (\(\Delta C_{NET\space{PRJ}}\)) is negative, indicating net emissions during the project, then these emissions are deducted from the reductions.
The resulting difference in net carbon stock changes is then multiplied by the market-effects leakage factor (\(LF_{ME}\)), derived in Chapter 19 , and the total uncertainty of the project (\(U_{total|LtPF}\)), calculated in Chapter 18 to derive the net GHG emission reductions.
\[ \begin{aligned} ER_t = & (C_{FUEL} - \min(0, C_{NET|BSL_{t*}}) + \min(0, \Delta C_{NET|PRJ}))\\ & \quad \times (1-LF_{ME}) \times (1-U_{total|LtPF}) \end{aligned} \tag{21.10}\]
Equation 21.11 (Eq. 41 of the VM0010 methods) describes the calculation of the net GHG emission removals in year t* since the start of the project activity, in the project scenario (\(CR_t\)). This is calculated as the difference between the net carbon stock changes in the project and baseline scenarios. If the net carbon stock change in the project scenario (\(\Delta C_{NET\space{PRJ}}\)) is negative, indicating net emissions during the project, then no removals are calculated. Likewise, if the net carbon stock change in the baseline scenario (\(\Delta C_{NET\space{BSL_{t*}}}\)) is positive, indicating there would have been net sequestration, then this is deducted from the project emission removals. As in Equation 21.10, the resulting difference in net carbon stock changes is then multiplied by the total uncertainty of the project (\(U_{total|LtPF}\)) to derive the net GHG emission removals.
\[ CR_t* = (\max(0, \Delta C_{NET|PRJ}) - \max(0, C_{NET|BSL_{t*}})) \times (1-U_{total|LtPF}) \tag{21.11}\]
21.0.3.2 Non-permanence risk buffer pool
Buffer credits to be deducted from removals in year t* (\(Bu_{CR_t*}\)) are derived as in Equation 21.12 (Eq. 43 of the VM0010 methods); where \(NPR\%\) is the overall project non-permanence risk rating converted to a percentage. \(NPR\%\) is derived from the VCS AFOLU Non-Permanence Risk Tool which, for the kuamut project, was 12%.
\[ Bu_{CR_t*} = (\max(0, \Delta C_{NET|PRJ}) - \max(0, C_{NET|BSL_{t*}})) \times NPR\% \tag{21.12}\]
Buffer credits to be deducted from reductions in year t* (\(Bu_{ER_t}\)) are derived as in Equation 21.13 (Eq. 44 of the VM0010 methods); in a comparable manner to the removals buffer pool calculation.
\[ Bu_{ER_t} = (\min(0, C_{NET|BSL_{t*}}) - \min(0, \Delta C_{NET|PRJ})) \times NPR\% \tag{21.13}\]
21.0.3.3 Verified Carbon Unit (VCU) calculations
The number of verified carbon units, in year t*, that result from project activities leading to removals (\(VCU_{CR_t*}\)) is calculated as in Equation 21.14 (Eq. 45 of the VM0010 methods). The number of verified carbon units that result from project activities leading to reductions (\(VCU_{ER_t}\)) is calculated as in Equation 21.15 (Eq. 46 of the VM0010 methods). Both of these equations are simply the net GHG emission reductions and removals, minus their respective buffer pool contribution. These values are rounded down to the nearest whole VCU.
\[ VCU_{CR_t*} = \lfloor CR_{t*} - Bu_{CR_t*} \rfloor \tag{21.14}\]
\[ VCU_{ER_t} = \lfloor ER_{t*} - Bu_{ER_t} \rfloor \tag{21.15}\]
For the monitoring periods 2016-2021 and 2022-2023, the project emissions, reductions and removals are outlined below in Table 21.1 and Table 21.2, respectively.
21.1 Code
Annualised Calculations Code R/annualised-calculations.R
#' The annualized calculations vary between years
#'
#' @param Parcels_src Returned list from `parcel_calculations` in
#' `ParcelCalculations_VM10v1.3.R`
#' @param mosaic_src mosaic area spatial polygon source
#' @param nfm_coupes_src nfm area spatial polygon source
#' @param nfm_lfme passed from from EstimateLeakage.R - scaling factor
#' (for nfm areas) by which to reduce credits based on leakage
#' @param mosaic_lfme passed from EstimateLeakage.R - scaling factor (for
#' mosaic areas) by which to reduce credits based on leakage
#' @param C_RG_PRJ A list of growth rates for each strata returned from
#' `calculate_proj_growth` in `R/proj-growth-rate-multi.R`
#' @param mgmt_strata A list of strata returned from `create_pre_16_strata` in
#' `R/strata.R`
#' @param mosaic_spcf A numeric species conservation factor for mosaic areas.
#' @param nfm_spcf A numeric species conservation factor for nfm areas.
#' @param mr_periods A list of monitoring report periods - must be a list of
#' numerics, each of which is length 2.
#' @param C_RG_planted Default is 3.0. See 'MosaicAreaGrowthRate.R for model
#' to estimate of mosaic planted growth rates
#' @param C_RG_unplanted Default is 1.6 Suarez 2019 'Refinement of IPCC default
#' rates ' 1.6=3.4*0.47
#' @param ProjectStart The first Creditable year of the project (i.e. 1 year
#' after the start of the project), default is 2016 for Kuamut
#' @param Duration The duration of the project in years, default is 30
#' @param tab_path The path to save the tables
#' @param mr_tab_path The path to save the Monitoring Report tables
#'
#' @return
#' @details
#' 8.1.6 Calculation of baseline scenario greenhouse gas emissions from change
#' in carbon stocks. This section calculates GHGNET|BSL, the net greenhouse gas
#' emissions in the baseline scenario, in tCO2e.
#'
#' Equation 10 (page 23):
#' carbon sequestration resulting from forest regrowth after timber harvest in
#' stratum i in land parcel p, tC ha-1 yr-1
#' Data not monitored in Equation 12 (page 26,VM0010v1.3)
annualised_calcs <- function(
Parcels_src,
mosaic_src,
nfm_coupes_src,
nfm_lfme,
mosaic_lfme,
deforest_calcs,
prj_ongo_gr,
mgmt_strata,
mosaic_spcf,
nfm_spcf,
mr_periods,
C_RG_planted = 3.0,
C_RG_unplanted = 1.6,
ProjectStart = 2016,
Duration = 30,
tab_path = "data_out/Routputs/Tables",
mr_tab_path = file.path(tab_path, "MR")
) {
# save option
to_save <- getOption("kuamut.save.outs", default = TRUE)
# -------------------------------------------------------------------------- #
# --------------------------- function setup ------------------------------- #
# -------------------------------------------------------------------------- #
# assert filepaths
purrr::walk(
c(Parcels_src, mosaic_src, nfm_coupes_src, unlist(mgmt_strata)),
assert_file_exists
)
# assert numerics
purrr::walk(
c(nfm_lfme, mosaic_lfme, unlist(prj_ongo_gr), C_RG_planted, C_RG_unplanted),
checkmate::assert_numeric
)
# assert mr periods
checkmate::assert_list(mr_periods)
purrr::map(mr_periods, ~ checkmate::assert_numeric(.x, len = 2))
checkmate::assert_set_equal(length(prj_ongo_gr), length(mr_periods))
CreditingEnd <- ProjectStart + (Duration - 1)
# -------------------------------------------------------------------------- #
# ------------------------- Baseline emissions ----------------------------- #
# -------------------------------------------------------------------------- #
# Pre process parcels and caluclate parcel level emissions.
parcel_emissions <- parcel_reader(Parcels_src, CreditingEnd, split = TRUE) |>
purrr::map(
~ logging_n_crediting(
.x,
crediting_end = CreditingEnd,
crg_planted = C_RG_planted,
crg_unplanted = C_RG_unplanted
)
)
# summing the parcels together
annual_baseline_emissions <- combine_bsl_parcel_emissions(parcel_emissions)
if (to_save) {
# --- SAVE TABLE: Annual baseline emissions
annual_bsl_em_tab(annual_baseline_emissions, tab_path)
# --- SAVE TABLE: MR Table 4.
purrr::iwalk(
mr_periods,
~ mr_bsl_em_tab(.x, .y, annual_baseline_emissions, mr_tab_path)
)
}
# -------------------------------------------------------------------------- #
# -------------------------- Project emissions ----------------------------- #
# -------------------------------------------------------------------------- #
# Page 37 and onwards of VM0010v1.3
# set up data frame of project-scenario deforestation emissions
prj_deforest_ems <- format_deforest_ems(deforest_calcs)
# ongoing forest growth
ongoing_for_gr_calcs <- parcel_reader(Parcels_src, CreditingEnd) |>
ongoing_forest_growth(
mos_spcf = mosaic_spcf,
nfm_spcf = nfm_spcf,
ongo_for_grow_rate = prj_ongo_gr,
mrperiods = mr_periods
)
ongoing_for_gr <- format_ongoing_forest_growth(
ongoing_for_gr_calcs,
CreditingEnd
)
prj_emissions <- combine_project_emissions(
proj_start = ProjectStart,
credit_end = CreditingEnd,
proj_defor_em = prj_deforest_ems,
proj_for_gr = ongoing_for_gr
)
mr_non_fire_ghge <- continuous_deforest_est(
deforest_calcs,
mr_periods
)
# --- SAVE TABLE: MR Table 7.Net GHG emissions resulting from non-fire dist.
if (to_save) {
purrr::iwalk(
mr_periods,
~ mr_deforest_ems_tab(.x, .y, mr_non_fire_ghge, mr_tab_path)
)
}
# --- SAVE TABLE: MR tab 8 Greenhouse gas emissions in the project
mr_proj_ghg_ems_list <- purrr::imap(
mr_periods,
~ prj_ems_tabs(.x, .y, prj_emissions, mr_tab_path)
)
# -------------------------------------------------------------------------- #
# ---------------------------- Market Leakage ------------------------------ #
# -------------------------------------------------------------------------- #
# Leakage factors are derived in "R/EstimateMarketLeakage.R"
# and are passed to this function as `nfm_lfme` and `mosaic_lfme`
lf_me <- area_weighted_leakage_factor(
mos_src = mosaic_src,
nfm_src = nfm_coupes_src,
mos_lf = mosaic_lfme,
nfm_lf = nfm_lfme
)
# -------------------------------------------------------------------------- #
# ------------ Summary of GHG Emission Reduction and/or Removal ------------ #
# -------------------------------------------------------------------------- #
# Merge project and BSL
vcu_df <- calculate_vcus(annual_baseline_emissions, prj_emissions, lf_me)
# --- SAVE TABLES: GHG ERRs VM0010 2045 (full table)
# this returns the dataframe with verbose column names.
vcu_calcs_2016_2045 <- vcu_full_tab(
vcu_df,
tab_path,
max(unlist(mr_periods))
)
# --- SAVE TABLE: MR tab 11 Net GHG Emission Reductions and Removals for each
# monitoring period
mr_net_vcu_list <- purrr::imap(
mr_periods,
~ {
mr_vcu_calcs_tab(
.x,
.y,
vcu_calcs_2016_2045,
mr_tab_path,
export = to_save
)
}
)
return(list(
ghg_vm10_proj = vcu_calcs_2016_2045,
mr_fire_area = mr_non_fire_ghge,
mr_act_ghge = mr_proj_ghg_ems_list,
mr_ghg_em_red_rem = mr_net_vcu_list,
vcu_df = vcu_df,
lkg_factor = lf_me
))
}
Baseline Emission Reductions Functions R/err_functions_baseline.R
#' wrapper for reading logging parcel
#' data is cleaned and then split by year and strata.
#' @param parcel_csv path to the parcel data csv file.
#' @return a list of dataframes, each dataframe is a year and strata.
#' @details
#' drop unrequired column V_EX.
#' For these calculations we ignore any parcels that are projected to be logged
#' after the crediting period (here 30 years duration)
parcel_reader <- function(parcel_csv, crediting_end, split = FALSE) {
parcels <- read.csv(parcel_csv) |>
dplyr::filter(LogYear <= crediting_end) |>
select(!V_EX)
if (isTRUE(split)) {
parcels <- split(
parcels, list(parcels$LogYear, parcels$Strata),
drop = TRUE
)
}
return(parcels)
}
#' expand a single row dataframe, for a given parcel to give baselline emmsions.
#' Each parcel is expanded to give rows for each year of the project scenario.
#' factoring in estimated baseline growth rates.
#' @param df data frame of emissions for each parcel/logging year.
#' @return a data frame with rows for each year of the project scenario.
#' @details
#' This sets up the baseline processing dataframe, from here, it is reduced and
#' calculations are derived.
#' Define VM0010 v1.3's area parameters
#' A1 = Area logged the year just passed
#' directly from parcel ha (as parcels are yearly)
#' and then 0's once all is logged (depends on parcel size and length of
#' time to log)
#' A1 # (Page 35 in VM0010 v1.3)
#' A2to10 (Page 35 in VM0010 v1.3)
#' A11to20 (Page 36 in VM0010 v1.3)
#' Expand to 20 years of project for the 'annualised calculations' (page 24)
#' updated for longer crediting periods
logging_n_crediting <- function(
df,
crediting_end,
crg_planted,
crg_unplanted) {
df <- tidyr::expand(df, df,
CreditYear = seq(from = LogYear, to = crediting_end)
)
if (nrow(df) < 11) {
A11to20_val <- rep(0, length.out = nrow(df))
} else {
A11to20_val <- c(
rep(0, length.out = 10),
rep(df$Area_ha[1], length.out = min(10, nrow(df) - 10)),
rep(0, length.out = max(0, nrow(df) - 20))
)
}
df |>
dplyr::mutate(
A1 = c(df$Area_ha[1], rep(0, n() - 1)),
A2to10 = c(
0, rep(df$Area_ha[1], length.out = min(9, n() - 1)),
rep(0, length.out = max(0, n() - 10))
),
A11to20 = A11to20_val,
# Equation 23 (page 34,VM0010 v1.4)
dC_NET_BSL1 = A1 * ((dC_DW_Slash / 10) + C_WP0 + (C_WP100 / 20)),
# Equation 24 (Page 35 ,VM0010v1.4)
dC_NET_BSL2to10 = A2to10 * ((dC_DW_Slash / 10) + (C_WP100 / 20)),
# Eleven to Twenty years
# Note logging slash is now all decayed
# Equation 25 (Page 35 ,VM0010v1.4)
dC_NET_BSL11to20 = A11to20 * (C_WP100 / 20),
# Equation 26, (Page 36 ,VM0010v1.4)
# the sequestration in the baseline since the logging
# if the strata is planted in the baseline, gets planted growth rate,
# otherwise the unplanted growth rate.
dC_NET_BSL1PLUS = case_when(
# Area multiplied by the positive growth - implemented in v1.4 -
# changed from multiplying by the negative growth in v1.3
Plant == "planted" ~ Area_ha * crg_planted,
TRUE ~ Area_ha * crg_unplanted
),
# Equation 27, (Page 36 ,VM0010 v1.4)
# changed in v1.4 so that emissions are negative and growth is positive
dC_NET_BSL_t = -dC_NET_BSL1 - dC_NET_BSL2to10 -
dC_NET_BSL11to20 + dC_NET_BSL1PLUS
)
}
#' Combine the parcel level emissions estimates
#' spatial averaging of parcel level emissions by year.
#' @param parcels_df_list a list of dataframes, each from `logging_n_crediting`
#' @return A tibble comprising the following columns:
#' CreditYear, dC_NET_BSL_t, GHG_NET_BSL_yearly, GHG_NET_BSL
combine_bsl_parcel_emissions <- function(parcels_df_list) {
parcels_df_list |>
# drop unnecessary columns, rename dc_NET_BSL_t based on list name
# which includes the year of harvest and strata.
purrr::imap(function(df, .name) {
.name <- paste0("dC_NET_BSL_t_Parcel", .name)
df |>
dplyr::select(CreditYear, dC_NET_BSL_t) |>
dplyr::rename(!!.name := dC_NET_BSL_t)
}) |>
# left join all the items in the list.
purrr::reduce(left_join, by = "CreditYear") |>
dplyr::rowwise() |>
# sum across the parcels to annualised the emissions
dplyr::mutate(dC_NET_BSL_t = sum(
dplyr::c_across(`dC_NET_BSL_t_Parcel2016.Mosaic-planted`:
`dC_NET_BSL_t_Parcel2043.NFM`),
na.rm = TRUE
)) |>
dplyr::ungroup() |>
dplyr::select(CreditYear, dC_NET_BSL_t) |>
# Equation 28, (Page 37 ,VM0010v1.3)
dplyr::mutate(GHG_NET_BSL_yr = dC_NET_BSL_t * (44 / 12)) |>
# Cumulative sum
dplyr::mutate(GHG_NET_BSL_cum = cumsum(GHG_NET_BSL_yr))
}
#' Export the baseline emissions table for entire proj period
#' @param abe the annual baseline emsissions output from
#' `combine_bsl_parcel_emissions`
#' @param .tab_path the directory path to save the table
#' @return NULL
annual_bsl_em_tab <- function(abe, .tab_path) {
abe |>
rename_all(~ c(
"Year", "dC_NET_BSL_t", "GHG_NET_BSL yearly",
"GHG_NET_BSL Cumulative"
)) |>
export_tab_n_csv("tab_GHG_BSL_2045", .tab_path, .digits = 2)
}
#' Export the baseline emissions table for a monitoring period
#' @param .mr_periods a vector of start and end years for a monitoring period
#' @param .mr the monitoring period number i.e. and integer (1, 2, 3, ...)
#' @param abe the annual baseline emsissions output from
#' `combine_bsl_parcel_emissions`
#' @param .tab_path the directory path to save the table
#' @return NULL
mr_bsl_em_tab <- function(.mr_periods, .mr, abe, .tab_path) {
abe |>
dplyr::filter(CreditYear %in% seq(min(.mr_periods), max(.mr_periods))) |>
dplyr::rename_with(~ c(
"Year that logging would occur according to the timber harvesting plan",
"Net change in carbon stock across all parcels in the baseline scenario in year t* (tC)",
"Net greenhouse gas emissions in the baseline scenario in year t* (tCO2e)",
"Cumulative net greenhouse gas emissions in the baseline scenario in year t* since the start of the project activity"
)) |>
dplyr::mutate(dplyr::across(
dplyr::where(is.numeric), \(x) round(x, 4)
)) |>
export_tab_n_csv(
glue::glue("mr_{.mr}_tab4_Net_GHG_{min(.mr_periods)}_{max(.mr_periods)}"),
.tab_path
)
}
Project Emission Removals Functions R/err_functions_project.R
#' Reformat the deforestation emissions data frame for annual err calcs
#' @param x a data frame of deforestation emissions
#' @return a tibble with the following columns:
#' CreditYear, dC_DIST_IL
format_deforest_ems <- function(x) {
x |>
dplyr::rename(CreditYear = Period) |>
select(CreditYear, dC_DIST_IL = `C_DIST_IL_i_t_PRJ`)
}
#' build a lookup dataframe to get the growth rates for each year
#' @param x a list of vectors, each vector is a start and end year
#' @param max_log_year the maximum logging year.
#' @param grs a list of vectors, each with growth rates for each strata
#' @return a tibble with the following columns:
#' proj_yr, `Mosaic-planted`, `Mosaic-unplanted`, `NFM`, `Inoperable (No Go)`
build_gr_seq <- function(x, max_log_year, grs) {
gr_seq <- purrr::map(x, ~ seq(.x[1], .x[2], by = 1))
gr_seq[length(gr_seq)] <- list(
seq(
min(gr_seq[[length(gr_seq)]]),
max_log_year
),
by = 1
)
purrr::map2(gr_seq, grs, function(x, y) {
bind_cols(
tibble::tibble(proj_yr = x),
pivot_wider(tibble::enframe(y), names_from = name, values_from = value)
)
}) |>
purrr::list_rbind()
}
#' Calculate the ongoing forest growth
#' @param parcels a data frame of parcels
#' @param mos_spcf the species conservation factor for mosaic strata
#' @param nfm_spcf the species conservation factor for nfm strata
#' @param ongo_for_grow_rate a list of vectors, with growth rates for strata
#' @param mrperiods a list of vectors, each vector is a start and end year
#' @return a tibble with the following columns:
#' LogYear, annual_for_gr, Area_ha accum_gr, cum_area, annual_for_gr_cs,
#' accum_gr_cs
ongoing_forest_growth <- function(
parcels,
mos_spcf,
nfm_spcf,
ongo_for_grow_rate,
mrperiods
) {
gr_seq <- suppressWarnings(
build_gr_seq(mrperiods, max(parcels$LogYear), ongo_for_grow_rate)
)
gr_query <- function(yr, strata) {
gr_seq[gr_seq$proj_yr == yr, strata][[1]]
}
ps <- parcels |>
dplyr::arrange(LogYear) |>
dplyr::select(LogYear, Area_ha, Strata, Rotation) |>
dplyr::filter(Rotation == "First") |>
dplyr::rowwise() |>
dplyr::mutate(
annual_for_gr = dplyr::case_when(
Strata %in% c("Mosaic-planted", "Mosaic-unplanted") ~
(gr_query(LogYear, Strata) * mos_spcf) * Area_ha * (44 / 12),
Strata == "NFM" ~
(gr_query(LogYear, Strata) * nfm_spcf) * Area_ha * (44 / 12)
)
) |>
dplyr::ungroup() |>
dplyr::group_by(LogYear) |>
dplyr::summarise(
annual_for_gr = sum(annual_for_gr),
Area_ha = sum(Area_ha)
) |>
tidyr::complete(
LogYear = seq(min(LogYear), max(LogYear), by = 1),
fill = list(annual_for_gr = 0, Area_ha = 0)
) |>
dplyr::mutate(
accum_gr = annual_for_gr * (LogYear - min(LogYear)),
cum_area = cumsum(Area_ha),
annual_for_gr_cs = cumsum(annual_for_gr),
accum_gr_cs_agg = annual_for_gr_cs + accum_gr,
accum_gr_cs = dplyr::case_when(
LogYear <= 2021 ~ accum_gr_cs_agg,
TRUE ~ annual_for_gr_cs
)
)
return(ps)
}
#' Reformat the ongoing forest growth data frame for annual err calcs
#' @param ofg a data frame of ongoing forest growth from `ongoing_forest_growth`
#' @return a tibble with the following columns:
#' CreditYear, dC_AB
format_ongoing_forest_growth <- function(ofg, credit_end) {
ofg |>
dplyr::select(CreditYear = LogYear, dC_AB = accum_gr_cs) |>
tidyr::complete(
CreditYear = seq(min(CreditYear), credit_end, by = 1)
) |>
dplyr::mutate(
dC_AB = case_when(
is.na(dC_AB) ~ max(ofg$annual_for_gr_cs),
TRUE ~ dC_AB
)
)
}
#' Combine the project emissions
#' @description combine illegal deforestation, forest growth and disturbances.
#' @param proj_start the start year of the project
#' @param credit_end the end year of the project
#' @param proj_defor_em a tibble of deforestation emissions
#' @param proj_for_gr a tibble of ongoing forest growth
#' @return a tibble with the following columns:
#' CreditYear, dC_DIST_IL, dC_AB dC_DIST_FR, B_PRJ, dC_DIST,
#' dC_NET_PRJ, GHG_NET_PRJ
#' @details
#' Note that fire is assumed to be zero. this will be updated in the event that
#' any fire occurs. non-fire disturbances are also assumed to be zero. However,
#' both of these disturbances will be captured in the biomass mapping.
combine_project_emissions <- function(
proj_start,
credit_end,
proj_defor_em,
proj_for_gr
) {
expand.grid(CreditYear = c(proj_start:credit_end)) |>
#----DISTURBANCE (illegal logging, etc) -------#
left_join(proj_defor_em, by = "CreditYear") |>
tidyr::replace_na(list(dC_DIST_IL = 0)) |>
dplyr::left_join(proj_for_gr, by = "CreditYear") |>
mutate(
# Equation 33 (Page 42, VM0010 v1.4)
# There was no fire. If there is, define it here
dC_DIST_FR = 0,
## basically AGB in the project but not in the baseline
# t d. m. ha-1 so MG per hectare;
B_PRJ = 1,
## Equation 35
# Non-fire disturbances (natural) that occur 'ex post' in the project area
# Unlikely to occur in Kuamut project. If they do define here
dC_DIST = 0,
# Equation 38 (Page 46, VM0010 v1.4)
# updated for v1.4 now - disturbance is now subtracted from biomass
# accumulation to make ensure that sequestration is a positive value.
dC_NET_PRJ = dC_AB - (dC_DIST_FR + dC_DIST + dC_DIST_IL),
# Equation 39 (Page 47, VM0010 v1.4)
# The net greenhouse gas emissions across in the project scenario
# SINCE THE START of the project activity is
# calculated as:
GHG_NET_PRJ = cumsum(dC_NET_PRJ)
) |>
tibble::as_tibble()
}
#' creates a continuous dataframe for deforestation emissions
#' @param deforest_df a tibble of deforestation emissions
#' @param mrperiods a list of vectors, each vector is a start and end year
#' @return a tibble with the following columns:
#' Period, `Deforest Area`, `C_DIST_IL_i_t_PRJ`
continuous_deforest_est <- function(deforest_df, mrperiods) {
mryears <- unlist(mrperiods)
defor_template <- tibble(
Period = seq(min(mryears), max(mryears)),
`Deforest Area` = 0,
`C_DIST_IL_i_t_PRJ` = 0
)
deforest_df |>
dplyr::full_join(
defor_template,
by = "Period",
suffix = c(".defor", ".template")
) |>
dplyr::mutate(
`Deforest Area` = coalesce(
`Deforest Area.defor`,
`Deforest Area.template`
),
`C_DIST_IL_i_t_PRJ` = coalesce(
`C_DIST_IL_i_t_PRJ.defor`,
`C_DIST_IL_i_t_PRJ.template`
)
) |>
dplyr::select(Period, `Deforest Area`, `C_DIST_IL_i_t_PRJ`) |>
dplyr::arrange(Period)
}
#' create and export the deforestation emissions table for each MR
#' @param mrperiod a vector of start and end years for a monitoring period
#' @param .mr the monitoring period number i.e. and integer (1, 2, 3, ...)
#' @param cont_defor a tibble of continuous deforestation emissions from
#' `continuous_deforest_est`
#' @param .tab_path the directory path to save the table aned csv
#' @return NULL
#'
mr_deforest_ems_tab <- function(mrperiod, .mr, cont_defor, .tab_path) {
mr_non_fire_ghge <- cont_defor |>
dplyr::select(
Year = Period,
,
`Area disturbed at time t (ha)` = `Deforest Area`,
`Net greenhouse gas emissions resulting from non-fire natural disturbance in year t (tCO2e)` = `C_DIST_IL_i_t_PRJ`
) |>
dplyr::filter(Year %in% seq(min(mrperiod), max(mrperiod)))
tab_name <- glue::glue(
"mr_{.mr}_tab7_Net_GHG_non_fire_{min(mrperiod)}_{max(mrperiod)}"
)
export_tab_n_csv(mr_non_fire_ghge, tab_name, .tab_path)
}
#' create and export the project-level emissions tables for each MR
#' @param mrperiods a list of vectors, each vector is a start and end year
#' @param .mr the monitoring period number i.e. and integer (1, 2, 3, ...)
#' @param prj_ems a tibble of project emissions from `combine_project_emissions`
#' @param .tab_path the directory path to save the table aned csv
#' @return NULL
#'
prj_ems_tabs <- function(mrperiods, .mr, prj_ems, .tab_path) {
mr_actual_ghge_proj <- prj_ems |>
dplyr::filter(dplyr::between(CreditYear, min(mrperiods), max(mrperiods))) |>
dplyr::select(
Year = CreditYear,
`Net greenhouse gas emissions resulting from non-fire disturbance and illegal logging (tCO2e)` = dC_DIST_IL,
`Annual carbon stock change in aboveground biomass of trees in year t, (tCO2e)` = dC_AB,
`Net greenhouse gas emissions in the project scenario in year t* (tCO2e)` = dC_NET_PRJ,
`Cumulative net greenhouse gas emissions in the project scenario in year t* since the start of the project activity` = GHG_NET_PRJ
) |>
dplyr::mutate(
`Net greenhouse gas emissions resulting from fire disturbance in year t (tCO2e)` = 0,
across(where(is.numeric), ~ round(.x, 3))
) |>
dplyr::relocate(
`Net greenhouse gas emissions resulting from fire disturbance in year t (tCO2e)`,
.after = "Year"
) |>
tibble::tibble()
# MR Tab5: Annual carbon stock change in aboveground biomass of trees in
# the project area
mr_cstock_change <- mr_actual_ghge_proj |>
dplyr::select(
Year,
`Annual carbon stock change in aboveground biomass of trees in year t, (tCO2e)`
)
tab_5_name <- glue::glue(
"mr_{.mr}_tab5_cstock_change_{min(mrperiods)}_{max(mrperiods)}"
)
tab8_name <- glue::glue(
"mr_{.mr}_tab8_Act_GHG_em_proj_{min(mrperiods)}_{max(mrperiods)}"
)
if (getOption("kuamut.save.outs", default = TRUE)) {
export_tab_n_csv(mr_cstock_change, tab_5_name, .tab_path)
export_tab_n_csv(mr_actual_ghge_proj, tab8_name, .tab_path)
}
return(mr_actual_ghge_proj)
}
Leakage Removal Functions R/err_functions_leakage.R
#' Calculate the area weighted market leakage factor.
#' derived from nfm and mosaic leakage factors from `estimate_market_leakage`.
#' in "R/EstimateMarketLeakage.R"
#' @param mos_src the source file for the mosaic strata
#' @param nfm_src the source file for the nfm strata
#' @param mos_lf the leakage factor for the mosaic strata
#' @param nfm_lf the leakage factor for the nfm strata
#' @return the area weighted leakage factor
#' @details
#' This function is called from the annual calculations function, as part of the
#' final ERR calcs.
#' A single leakage factor is required for the ERR calculations and therefore
#' we derive an area-weighted leakage factor for the project area. see
#' VM10, page 50... 'multiple values of LFME result', then an area weighted
#' final value for LFME shall be calculated. The area of stratum i as a
#' proportion of the total project area shall be multiplied. All values are
#' then summed to arrive at the area weighted final value of LFME.
area_weighted_leakage_factor <- function(
mos_src, nfm_src, mos_lf, nfm_lf) {
mos <- sf::read_sf(mos_src) |>
dplyr::summarise()
mos_area <- sf::st_area(mos) |>
units::set_units(ha) |>
as.numeric()
## Area for IFM
nfm <- sf::read_sf(nfm_src)
nfm_area <- sum(sf::st_area(nfm)) |>
units::set_units(ha) |>
as.numeric()
# total active area logged in baseline
tot_area <- nfm_area + mos_area
# Leakage mosaic multiplied by proportion mosaic
lf_me_mos <- mos_lf * (mos_area / tot_area)
# Leakage IFM multiplied by proportion IFM
lf_me_nfm <- nfm_lf * (nfm_area / tot_area)
## Final area weighted value of LE_ME
round(lf_me_mos + lf_me_nfm, 3)
}
#' (DEPRECATED) Apply the leakage factor to the baseline emissions
#' @param bsl_ems the baseline emissions data frame
#' @param lf the leakage factor (project-level and area weighted if required)
#' @return a tibble with the leakage factor applied to the baseline emissions
#' and the following columns: CreditYear, dC_NET_BSL_t, GHG_NET_BSL_yearly,
#' GHG_NET_BSL, GHG_LK, GHG_LK_yearly
#' @details
#' Equation 40 (page 49, VM0010v1.3)
apply_leakage_to_bsl <- function(bsl_ems, lf) {
bsl_ems |>
mutate(
GHG_LK_yr = lf * GHG_NET_BSL_yr,
GHG_LK_cum = cumsum(GHG_LK_yr)
)
}
#' (DEPRECATED) Export monitoring report leakage table (tab 31)
#' @param bsl_post_leak the baseline emissions with leakage applied from
#' `apply_leakage_to_bsl`
#' @param .tab_path the directory path to save the table
#' @return NULL
mr_leakage_tab <- function(bsl_post_leak, .tab_path) {
bsl_post_leak |>
dplyr::select(
Year = CreditYear,
`Market leakage as a result of IFM LtPF activities in year t* (tCO2e)` = GHG_LK_yr,
`Total cumulative leakage in year t* since the start of the project activity(tCO2e)` = GHG_LK_cum
) |>
dplyr::mutate("Leakage due to activity shifting (tCO2e)" = 0) |>
dplyr::relocate(4, .after = 1) |>
export_tab_n_csv("tab31_leak_emmiss_2045", .tab_path)
}
Emissions Summary Functions R/err_functions_summarise.R
#' calculate the net Verified Carbon Units (VCUs) for a monitoring period
#' @description Uses VM0010 v1.4 equations 40, 41, 43, 44, 45, 46 to calculate
#' the net VCUs for a monitoring period, split into carbon removals and
#' emissions.
#' @param bsl_emissions data.frame of the baseline emissions
#' @param prj_emissions data.frame of the project emissions
#' @param leak_factor numeric length 1; leakage factor for for market-effects
#' calculations
#' @param cfuel numeric length 1; l carbon emissions associated with the
#' combustion of fossil fuel in forestry and wood processing machinery
#' @param utot numeric length 1; Total uncertainty for LtPF Project
#' (zero if < 15%)
#' @param npr numeric length 1; Overall project non-permanence risk rating
#' converted to a percentage.
#' @return a tibble with the following columns: credit_year, c_net_bsl,
#' c_net_prj, er_t, cr_t, bu_cr, bu_er, vcu_cr_t, vcu_er_t, net_vcu.
#' @details
#' This is the latest version of the final derivation of the net VCUs for a
#' monitoring period. It implements the equations from VM0010 v1.4. The key
#' key differences compared to v1.3 are the explicit seperation of reductions
#' and removals and the calculation of the buffer based on the pre-leakage
#' difference between the baseline and project emissions.
calculate_vcus <- function(
bsl_emissions, prj_emissions, leak_factor,
cfuel = 0, utot = 0, npr = 0.12) {
checkmate::assert_class(bsl_emissions, "data.frame")
checkmate::assert_class(prj_emissions, "data.frame")
checkmate::assert_numeric(leak_factor, len = 1)
checkmate::assert_numeric(cfuel, len = 1)
checkmate::assert_numeric(utot, len = 1)
checkmate::assert_numeric(npr, len = 1)
# browser()
dplyr::left_join(
dplyr::select(bsl_emissions,
credit_year = CreditYear, c_net_bsl = GHG_NET_BSL_yr
),
dplyr::select(prj_emissions,
credit_year = CreditYear, c_net_prj = dC_NET_PRJ,
),
by = "credit_year"
) |>
dplyr::mutate(
# eq. 40 in VM0010 v1.4
er_t = (cfuel - pmin(0, c_net_bsl) + pmin(0, c_net_prj)) *
(1 - leak_factor) * (1 - utot),
# eq. 41 in VM0010 v1.4
cr_t = (pmax(0, c_net_prj) - pmax(0, c_net_bsl)) * (1 - utot),
# calculate leakage explicitly for final tab
leak_emissions =
(cfuel - pmin(0, c_net_bsl) + pmin(0, c_net_prj)) * leak_factor,
# eq. 43 in VM0010 v1.4
bu_cr = ceiling((pmax(0, c_net_prj) - pmax(0, c_net_bsl)) * npr),
# eq. 44 in VM0010 v1.4
# This conditional is required because v1.3 was used for the first
# monitoring period. Post 2021 VM0010 v1.4 is used.
bu_er = ceiling((pmin(0, c_net_prj) - pmin(0, c_net_bsl)) * npr),
# total buffer pool for final table
buffer_pool = dplyr::case_when(
# to facilitate historic 1.3 calcs
credit_year <= 2021 ~ round((er_t + cr_t) * npr),
# for v1.4
TRUE ~ bu_cr + bu_er
),
vcu_cr_t = dplyr::case_when(
credit_year <= 2021 ~ round(
(floor((er_t + cr_t)) - buffer_pool) * (cr_t / (er_t + cr_t))
),
# eq. 45 in VM0010 v1.4
TRUE ~ floor(cr_t - bu_cr)
),
vcu_er_t = dplyr::case_when(
credit_year <= 2021 ~ round(
(floor((er_t + cr_t)) - buffer_pool) * (er_t / (er_t + cr_t))
),
# eq. 46 in VM0010 v1.4
TRUE ~ floor(er_t - bu_er)
),
net_vcu = vcu_cr_t + vcu_er_t
)
}
vcu_full_tab <- function(vcu_tab, .tab_path, latest_mr) {
vcu <- vcu_tab |>
dplyr::select(
`Vintage period` = credit_year,
`Estimated baseline emissions` = c_net_bsl,
`Estimated project emissions` = c_net_prj,
`Estimated leakage emissions` = leak_emissions,
`Estimated reduction buffer pool` = bu_er,
`Estimated removal buffer pool` = bu_cr,
`Estimated buffer pool allocation` = buffer_pool,
`Estimated reduction VCUs` = vcu_er_t,
`Estimated removal VCUs` = vcu_cr_t,
`Estimated total VCU issuance` = net_vcu
) |>
dplyr::mutate(
`Estimate type` = dplyr::case_when(
`Vintage period` <= latest_mr ~ "Monitored",
`Vintage period` > latest_mr ~ "Projected"
)
)
if (getOption("kuamut.save.outs", default = TRUE)) {
export_tab_n_csv(vcu, "VCUs_VM0010_2045", .tab_path)
}
return(vcu)
}
mr_vcu_calcs_all_tab <- function(vcu_tab, .tab_path, latest_mr) {
vcu <- vcu_tab |>
dplyr::select(
`Vintage period` = credit_year,
`Estimated baseline emissions` = c_net_bsl,
`Estimated project emissions` = c_net_prj,
`Estimated leakage emissions` = leak_emissions,
`Estimated buffer pool allocation` = buffer_pool,
`Estimated reduction VCUs` = vcu_er_t,
`Estimated removal VCUs` = vcu_cr_t,
`Estimated total VCU issuance` = net_vcu
) |>
dplyr::mutate(
`Estimate type` = dplyr::case_when(
`Vintage period` <= latest_mr ~ "Monitored",
`Vintage period` > latest_mr ~ "Projected"
)
)
export_tab_n_csv(vcu, "VCUs_ERRs_2016_2045", .tab_path)
return(vcu)
}
#' Create the final VCU table for a monitoring period
#' @param mrperiod a vector of start and end years for a monitoring period
#' @param .mr the monitoring period number i.e. and integer (1, 2, 3, ...)
#' @param vcu_all a tibble of all monitoring period emissions from
#' `vcu_full_tab`
#' @param .tab_path the directory path to save the table and csv
#' @return a tibble
mr_vcu_calcs_tab <- function(mrperiod, .mr, vcu_all, .tab_path, export = TRUE) {
mr_net_vcu <- vcu_all |>
dplyr::select(!dplyr::all_of(
c(
"Estimate type", "Estimated reduction buffer pool",
"Estimated removal buffer pool"
)
)) |>
dplyr::filter(
dplyr::between(`Vintage period`, min(mrperiod), max(mrperiod))
) |>
dplyr::mutate(`Vintage period` = as.character(`Vintage period`))
mr_net_vcu_sum <- mr_net_vcu |>
dplyr::summarise(
dplyr::across(!dplyr::one_of("Vintage period"), ~ sum(.x))
) |>
dplyr::mutate(
`Vintage period` = "Total"
) |>
dplyr::relocate(`Vintage period`)
mr_net_vcu_bind <- dplyr::bind_rows(mr_net_vcu, mr_net_vcu_sum) |>
dplyr::mutate(dplyr::across(dplyr::where(is.numeric), ~ round(.x, 3)))
if (export) {
tab_name <- glue::glue(
"mr_{.mr}_Net_VCUs_{min(mrperiod)}_{max(mrperiod)}"
)
export_tab_n_csv(mr_net_vcu_bind, tab_name, .tab_path)
}
return(mr_net_vcu_bind)
}