This document outlines a simple function that calculates stand level SDI based on a path to a stdstk RDS file (derived from an FVS output database) and a path to the “maxSDIcodes.csv” that was aggregated from variant-specific FVS documents found online (currently it only has codes for CA and CO variants, since those are chosen for Sugarpine).
In this first step, simply state your paths. In this case, I used local paths, but the same principles should work for s3 and drive connections.
It is also necessary to state your variant, since the maxSDIcodes can change slightly from variant to variant.
stdstk_path <-
'/Users/eyackulic/Downloads/CR-StdStk.rds'
maxSDI_path <-
'/Users/eyackulic/Downloads/MaxSDICodes.csv'
variant <- 'CR'
Next, I declare the function that will take in these inputs and derive a stand level SDI value.
standSDI <- function(stdstk_path, maxSDI_path, variant){
stdstk <-
stdstk_path |>
readRDS() |>
dplyr::mutate(Variant = variant)
maxSDI <-
maxSDI_path |>
read.csv() |>
dplyr::select(Name, MaxSDI, Variant) |>
dplyr::rename(Species = Name)
stdstk |>
dplyr::left_join(maxSDI, by = c('Species', 'Variant')) |>
dplyr::group_by(StandID,Year, MgmtID) |>
dplyr::reframe(
Species = Species,
SumBA = LiveBA/sum(LiveBA),
MaxSDI = MaxSDI,
sdi_val = MaxSDI * SumBA)|>
dplyr::ungroup() |>
dplyr::group_by(StandID,Year, MgmtID) |>
dplyr::mutate(StandSDI = round(sum(sdi_val, na.rm = T), digits = 0)) |>
dplyr::select(StandID, Year, MgmtID, StandSDI) |>
dplyr::distinct()
}
In this snippet, I run an example of the function and show the outputs for one Stand and MgmtID. This stand was chosen because it had multiple species per year in the stdstk file, making it an ideal candidate to test that the function is working properly.
sample <- standSDI(stdstk_path, maxSDI_path, variant = 'CR')
sample |> dplyr::filter(StandID %in% 10003 & MgmtID %in%'CMCC') |> data.frame()
## StandID Year MgmtID StandSDI
## 1 10003 2025 CMCC 298
## 2 10003 2029 CMCC 297
## 3 10003 2030 CMCC 297
## 4 10003 2031 CMCC 284
## 5 10003 2035 CMCC 284
## 6 10003 2036 CMCC 284
## 7 10003 2040 CMCC 284
## 8 10003 2045 CMCC 284
## 9 10003 2050 CMCC 284
## 10 10003 2055 CMCC 284
## 11 10003 2060 CMCC 284
and here are the results of that same filter with the tree species ids preserved (line 82 commented out to show what is happening in the maths)
stdstk <-
stdstk_path |>
readRDS() |>
dplyr::mutate(Variant = variant)
maxSDI <-
maxSDI_path |>
read.csv() |>
dplyr::select(Name, MaxSDI, Variant) |>
dplyr::rename(Species = Name)
stdstk |>
dplyr::left_join(maxSDI, by = c('Species', 'Variant')) |>
dplyr::group_by(StandID,Year, MgmtID) |>
dplyr::reframe(
Species = Species,
SumBA = LiveBA/sum(LiveBA),
MaxSDI = MaxSDI,
sdi_val = MaxSDI * SumBA)|>
dplyr::ungroup() |>
dplyr::group_by(StandID,Year, MgmtID) |>
dplyr::mutate(StandSDI = round(sum(sdi_val, na.rm = T), digits = 0)) |>
# dplyr::select(StandID, Year, MgmtID, StandSDI) |>
dplyr::distinct() |>
dplyr::filter(StandID %in% 10003 & MgmtID %in%'CMCC') |>
data.frame()
## StandID Year MgmtID Species SumBA MaxSDI sdi_val StandSDI
## 1 10003 2025 CMCC 2TN 0.2144003 348 74.61131 298
## 2 10003 2025 CMCC QUEM 0.7855997 284 223.11031 298
## 3 10003 2029 CMCC 2TN 0.2042565 348 71.08126 297
## 4 10003 2029 CMCC QUEM 0.7957435 284 225.99115 297
## 5 10003 2030 CMCC 2TN 0.2025007 348 70.47025 297
## 6 10003 2030 CMCC QUEM 0.7974993 284 226.48980 297
## 7 10003 2031 CMCC QUEM 1.0000000 284 284.00000 284
## 8 10003 2035 CMCC QUEM 1.0000000 284 284.00000 284
## 9 10003 2036 CMCC QUEM 1.0000000 284 284.00000 284
## 10 10003 2040 CMCC QUEM 1.0000000 284 284.00000 284
## 11 10003 2045 CMCC QUEM 1.0000000 284 284.00000 284
## 12 10003 2050 CMCC QUEM 1.0000000 284 284.00000 284
## 13 10003 2055 CMCC QUEM 1.0000000 284 284.00000 284
## 14 10003 2060 CMCC QUEM 1.0000000 284 284.00000 284