Volume estimation and volumetric models

Let’s calculate the section volume of felled trees using Smalian’s method, according to the formula: \[ V_{secao} = \frac{AS_{i} + AS_{i+1}}{2} . L \]

We’ll use the exfm7 dataframe as an exemple:

library(forestmangr)
data(exfm7)
data_ex <- exfm7
data_ex
#> # A tibble: 3,393 x 11
#>   MAP     PROJECT SPACING STRATA GENCODE  TREE   DBH    TH    hi di_wb bark_t
#>   <chr>   <fct>   <fct>    <int> <fct>   <int> <dbl> <dbl> <dbl> <dbl>  <dbl>
#> 1 FOREST1 PEQUI   3x3          4 FM00100     1  12.4  22.1   0.1  13.1      6
#> 2 FOREST1 PEQUI   3x3          4 FM00100     1  12.4  22.1   0.5  12.6      6
#> 3 FOREST1 PEQUI   3x3          4 FM00100     1  12.4  22.1   1    12.4      5
#> 4 FOREST1 PEQUI   3x3          4 FM00100     1  12.4  22.1   1.5  12.3      5
#> 5 FOREST1 PEQUI   3x3          4 FM00100     1  12.4  22.1   2    11.8      4
#> 6 FOREST1 PEQUI   3x3          4 FM00100     1  12.4  22.1   4    11.3      4
#> # ... with 3,387 more rows

First we’ll calculate the volume with bark of each section with the smalianwb function. In it we input the dataframe, and names for the section diameter with bark, section height and tree variables:

data_ex_sma <- smalianwb(data_ex,"di_wb", "hi","TREE")
head(as.data.frame(data_ex_sma))
#>       MAP PROJECT SPACING STRATA GENCODE TREE      DBH   TH  hi    di_wb bark_t
#> 1 FOREST1   PEQUI     3x3      4 FM00100    1 12.41409 22.1 0.1 13.05071      6
#> 2 FOREST1   PEQUI     3x3      4 FM00100    1 12.41409 22.1 0.5 12.57324      6
#> 3 FOREST1   PEQUI     3x3      4 FM00100    1 12.41409 22.1 1.0 12.41409      5
#> 4 FOREST1   PEQUI     3x3      4 FM00100    1 12.41409 22.1 1.5 12.25493      5
#> 5 FOREST1   PEQUI     3x3      4 FM00100    1 12.41409 22.1 2.0 11.77747      4
#> 6 FOREST1   PEQUI     3x3      4 FM00100    1 12.41409 22.1 4.0 11.30000      4
#>       CSA_WB         VWB
#> 1 0.01337697 0.005158610
#> 2 0.01241607 0.006129952
#> 3 0.01210373 0.005974776
#> 4 0.01179537 0.005672382
#> 5 0.01089416 0.020922907
#> 6 0.01002875 0.018694737

Now, we’ll calculate the volume without bark per secction, using the smalianwb function. We’ll input the same variables as before, and the variable name for the bark thickness. In our data, this variable is in millimeters, so, we’ll use the bt_mm_to_cm as TRUE to convert it to centimeters:

data_ex_sma <- smalianwob(data_ex_sma,"di_wb","hi","bark_t","TREE",bt_mm_to_cm=T)
head(as.data.frame(data_ex_sma))
#>       MAP PROJECT SPACING STRATA GENCODE TREE      DBH   TH  hi    di_wb bark_t
#> 1 FOREST1   PEQUI     3x3      4 FM00100    1 12.41409 22.1 0.1 13.05071    0.6
#> 2 FOREST1   PEQUI     3x3      4 FM00100    1 12.41409 22.1 0.5 12.57324    0.6
#> 3 FOREST1   PEQUI     3x3      4 FM00100    1 12.41409 22.1 1.0 12.41409    0.5
#> 4 FOREST1   PEQUI     3x3      4 FM00100    1 12.41409 22.1 1.5 12.25493    0.5
#> 5 FOREST1   PEQUI     3x3      4 FM00100    1 12.41409 22.1 2.0 11.77747    0.4
#> 6 FOREST1   PEQUI     3x3      4 FM00100    1 12.41409 22.1 4.0 11.30000    0.4
#>       CSA_WB         VWB   di_wob     CSA_WOB        VWOB
#> 1 0.01337697 0.005158610 11.85071 0.011030070 0.004237849
#> 2 0.01241607 0.006129952 11.37324 0.010159172 0.005097861
#> 3 0.01210373 0.005974776 11.41409 0.010232273 0.005045296
#> 4 0.01179537 0.005672382 11.25493 0.009948911 0.004853333
#> 5 0.01089416 0.020922907 10.97747 0.009464421 0.018123438
#> 6 0.01002875 0.018694737 10.50000 0.008659016 0.016363277

This can be done directly using pipes (%>%):

data_ex_sma <- data_ex %>% 
  smalianwb("di_wb", "hi", "TREE") %>% 
  smalianwob("di_wb", "hi", "bark_t", "TREE", bt_mm_to_cm=T)
head(as.data.frame(data_ex_sma))
#>       MAP PROJECT SPACING STRATA GENCODE TREE      DBH   TH  hi    di_wb bark_t
#> 1 FOREST1   PEQUI     3x3      4 FM00100    1 12.41409 22.1 0.1 13.05071    0.6
#> 2 FOREST1   PEQUI     3x3      4 FM00100    1 12.41409 22.1 0.5 12.57324    0.6
#> 3 FOREST1   PEQUI     3x3      4 FM00100    1 12.41409 22.1 1.0 12.41409    0.5
#> 4 FOREST1   PEQUI     3x3      4 FM00100    1 12.41409 22.1 1.5 12.25493    0.5
#> 5 FOREST1   PEQUI     3x3      4 FM00100    1 12.41409 22.1 2.0 11.77747    0.4
#> 6 FOREST1   PEQUI     3x3      4 FM00100    1 12.41409 22.1 4.0 11.30000    0.4
#>       CSA_WB         VWB   di_wob     CSA_WOB        VWOB
#> 1 0.01337697 0.005158610 11.85071 0.011030070 0.004237849
#> 2 0.01241607 0.006129952 11.37324 0.010159172 0.005097861
#> 3 0.01210373 0.005974776 11.41409 0.010232273 0.005045296
#> 4 0.01179537 0.005672382 11.25493 0.009948911 0.004853333
#> 5 0.01089416 0.020922907 10.97747 0.009464421 0.018123438
#> 6 0.01002875 0.018694737 10.50000 0.008659016 0.016363277

We can also visualize the mean curve form of the trees in the area, using Kozak’s model with the average_tree_curve function:

avg_tree_curve(df=data_ex_sma,d="di_wb",dbh="DBH",h="hi",th="TH")

To calculate the volume of each tree, we’ll use the vol_summarise function. We input the data, and dbhm height, volume with bark, volume without bark and tree variables:

data_ex_vol_arvore <- vol_summarise(data_ex_sma, dbh = "DBH", th = "TH", 
                                  vwb="VWB",tree = "TREE",vwob="VWOB")
#> Warning: `funs()` was deprecated in dplyr 0.8.0.
#> Please use a list of either functions or lambdas: 
#> 
#>   # Simple named list: 
#>   list(mean = mean, median = median)
#> 
#>   # Auto named with `tibble::lst()`: 
#>   tibble::lst(mean, median)
#> 
#>   # Using lambdas
#>   list(~ mean(., trim = .2), ~ median(., na.rm = TRUE))
data_ex_vol_arvore
#> # A tibble: 197 x 10
#>    TREE   DBH    TH    CSA   VWB  VWOB  FFWB FFWOB FFWB_mean FFWOB_mean
#>   <int> <dbl> <dbl>  <dbl> <dbl> <dbl> <dbl> <dbl>     <dbl>      <dbl>
#> 1     1  12.4  22.1 0.0121 0.131 0.113 0.489 0.424     0.468      0.412
#> 2     2  13.1  22.3 0.0134 0.145 0.126 0.487 0.423     0.468      0.412
#> 3     3  13.2  20   0.0137 0.126 0.108 0.459 0.393     0.468      0.412
#> 4     4  13.2  19.4 0.0137 0.139 0.123 0.521 0.463     0.468      0.412
#> 5     5  13.4  23.7 0.0140 0.156 0.133 0.470 0.401     0.468      0.412
#> 6     6  13.5  21.5 0.0144 0.139 0.124 0.450 0.401     0.468      0.412
#> # ... with 191 more rows

Now to determine the most adequate volumetric model for this data, we’ll fit two models, and compare them using plots for their residuals with the resid_plot function.

Schumacher’s volumetric model: \[ Ln(V) = \beta_0 + \beta_1*Ln(dbh) + \beta_2*Ln(H) \]

Husch’s volumetric model: \[ Ln(V) = \beta_0 + \beta_1*Ln(dbh) \]

We’ll use the output “merge_est” from the lm_table function. This will estimate the volume for the observed data automatically. Then, we’ll use resid_plot to compare the observed variable with the estimated ones:

data_ex_vol_arvore %>% 
  lm_table(log(VWB) ~  log(DBH) + log(TH),output="merge_est",est.name="Schumacher") %>%
  lm_table(log(VWB) ~  log(DBH),output="merge_est",est.name="Husch") %>%
resid_plot("VWB", "Schumacher", "Husch")

Schumacher’s model was more symmetrical, and can be considered the better model for this dataset. To safe it’s coefficients in a dataframe, we’ll fit the model again, but with the standard output:

tabcoef_vwb <- lm_table(data_ex_vol_arvore, log(VWB) ~  log(DBH) + log(TH) )
tabcoef_vwb
#>          b0       b1        b2      Rsqr  Rsqr_adj  Std.Error
#> 1 -9.595863 1.889372 0.9071631 0.9966646 0.9966303 0.04855508

And do the same for the volume without bark:

tabcoef_vwob <- lm_table(data_ex_vol_arvore, log(VWOB) ~  log(DBH) + log(TH) )
tabcoef_vwob
#>          b0       b1       b2      Rsqr  Rsqr_adj  Std.Error
#> 1 -9.808975 1.918007 0.908154 0.9961152 0.9960752 0.05301495