Skip to content

Commit 991e5b7

Browse files
committed
add compute_ht_metrics()
1 parent 1e2df89 commit 991e5b7

5 files changed

Lines changed: 130 additions & 40 deletions

File tree

NAMESPACE

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
export(.get_fia_plot_geom)
44
export(.get_tree_list_xy)
55
export(DEFAULT_TREE_COLUMNS)
6+
export(compute_ht_metrics)
67
export(create_fia_owin)
78
export(create_fia_ppp)
89
export(load_tree_data)

R/compute_ht_metrics.R

Lines changed: 59 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -9,32 +9,38 @@
99
#' * `meanTreeHt`: mean height of trees `>= 5.0` in. (`12.7` cm) diameter
1010
#' * `meanTreeHtBAW`: basal-area weighted mean height of trees `>= 5.0` in.
1111
#' (`12.7` cm) diameter
12-
#' * `meanTreeHtDom`: mean height of canopy dominant/codominant trees
12+
#' * `meanTreeHtDom`: mean height of canopy dominant/co-dominant trees
1313
#' `>= 5.0` in. (`12.7` cm) diameter
1414
#' * `meanTreeHtDomBAW`: basal-area weighted mean height of canopy
15-
#' dominant/codominant trees `>= 5.0` in. (`12.7` cm) diameter
15+
#' dominant/co-dominant trees `>= 5.0` in. (`12.7` cm) diameter
1616
#' * `maxTreeHt`: height of the tallest tree `>= 5.0` in. (`12.7` cm) diameter
1717
#' * `predomTreeHt`: predominant tree height, as the mean height of the tallest
18-
#' trees `>= 5.0` in. (`12.7` cm) diameter comprising `16` trees per acre
19-
#' (`39.5` trees per hectare)
18+
#' trees `>= 5.0` in. (`12.7` cm) diameter comprising up to `16` trees per
19+
#' acre (`39.5` trees per hectare)
2020
#' * `meanSapHt`: mean height of saplings (trees `>= 1.0` in. diameter but
2121
#' `< 5.0` in. diameter, i.e., `>= 2.54` cm but `< 12.7` cm)
2222
#' * `maxSapHt`: height of the tallest sapling
2323
#'
24-
#' For the purpose of height calculations, canopy dominant/codominant include
25-
#' "open grown" trees, i.e., include trees with FIA crown class codes (`CCLCD`)
26-
#' of `1` (open grown), `2` (dominant) and `3` (codominant), but exclude trees
27-
#' with `CCLCD` of `4` (intermediate) and `5` (overtopped).
24+
#' For the purpose of height calculations, canopy dominant/co-dominant include
25+
#' "open grown" trees, i.e., include trees with FIA crown class code (`CCLCD`)
26+
#' of `1` (open grown), `2` (dominant) or `3` (co-dominant), but exclude trees
27+
#' with `CCLCD` of `4` (intermediate) or `5` (over-topped).
2828
#'
2929
#' @param tree_list A data frame with tree records for one FIA plot. Must have
3030
#' columns `DIA` (tree diameter), `HT` (tree height), `ACTUALHT` (tree actual
31-
#' height, `ACTUALHT < HT` indicating a broken top), `CCLCD1` (FIA crown class
31+
#' height, `ACTUALHT < HT` indicating a broken top), `CCLCD` (FIA crown class
3232
#' code), `TPA_UNADJ` (trees per acre).
33+
#' @param digits Optional integer indicating the number of digits to keep in the
34+
#' return values (defaults to `1`).
3335
#' @return
34-
#' A named list of height metrics computed for the input tree list, as described
36+
#' A named list of computed height metrics for the input tree list, as described
3537
#' in Details.
3638
#'
37-
compute_ht_metrics <- function(tree_list) {
39+
#' @examples
40+
#' compute_ht_metrics(plantation)
41+
#'
42+
#' @export
43+
compute_ht_metrics <- function(tree_list, digits = 1) {
3844

3945
if (missing(tree_list) || is.null(tree_list))
4046
stop("'tree_list' is required", call. = FALSE)
@@ -47,6 +53,9 @@ compute_ht_metrics <- function(tree_list) {
4753
if (!all(required_cols %in% colnames(tree_list)))
4854
stop("'tree_list' is missing required columns", call. = FALSE)
4955

56+
if (is.null(digits))
57+
digits <- 1
58+
5059
# separate "trees" vs "saplings" here
5160
if ("STATUSCD" %in% colnames(tree_list)) {
5261
trees_in <- tree_list[tree_list$STATUSCD == 1 & tree_list$DIA >= 5, ]
@@ -65,42 +74,52 @@ compute_ht_metrics <- function(tree_list) {
6574
warning("one or more sapling heights are missing", call. = FALSE)
6675

6776
ht_metrics <- vector(mode = "list", length = 8)
77+
ht_metrics[1:length(ht_metrics)] <- 0 # by definition
6878
names(ht_metrics) <- c("meanTreeHt", "meanTreeHtBAW", "meanTreeHtDom",
6979
"meanTreeHtDomBAW", "maxTreeHt", "predomTreeHt",
7080
"meanSapHt", "maxSapHt")
7181

72-
basal_area <- pi * (trees_in$DIA / 2)^2
73-
74-
ht_metrics$meanTreeHt <- mean(tree_ht, na.rm = TRUE)
75-
ht_metrics$meanTreeHtBAW <- stats::weighted.mean(tree_ht, basal_area,
76-
na.rm = TRUE)
77-
78-
tree_ht_doms <- tree_ht[trees_in$CCLCD %in% c(1, 2, 3)]
79-
ht_metrics$meanTreeHtDom <- mean(tree_ht_doms, na.rm = TRUE)
80-
81-
basal_area_doms <- basal_area[trees_in$CCLCD %in% c(1, 2, 3)]
82-
ht_metrics$meanTreeHtDomBAW <-
83-
stats::weighted.mean(tree_ht_doms, basal_area_doms, na.rm = TRUE)
84-
85-
ht_metrics$maxTreeHt <- max(tree_ht, na.rm = TRUE)
86-
87-
tree_ht_tpa <- data.frame(tree_ht, trees_in$TPA_UNADJ, check.names = FALSE)
88-
tree_ht_tpa <- tree_ht_tpa[order(tree_ht, decreasing = TRUE), ]
89-
tpa <- 0
90-
sum_ht <- 0
91-
n <- 0
92-
for (i in seq_len(nrow(tree_ht_tpa))) {
93-
sum_ht <- sum_ht + tree_ht_tpa[i, 1]
94-
tpa <- tpa + tree_ht_tpa[i, 2]
95-
n <- n + 1
96-
if (tpa > 16)
97-
break
82+
if (nrow(trees_in) > 0) {
83+
basal_area <- pi * (trees_in$DIA / 2)^2
84+
ht_metrics$meanTreeHt <-
85+
round(mean(tree_ht, na.rm = TRUE), digits = digits)
86+
87+
ht_metrics$meanTreeHtBAW <-
88+
round(stats::weighted.mean(tree_ht, basal_area, na.rm = TRUE),
89+
digits = digits)
90+
91+
tree_ht_doms <- tree_ht[trees_in$CCLCD %in% c(1, 2, 3)]
92+
basal_area_doms <- basal_area[trees_in$CCLCD %in% c(1, 2, 3)]
93+
ht_metrics$meanTreeHtDom <-
94+
round(mean(tree_ht_doms, na.rm = TRUE), digits = digits)
95+
96+
ht_metrics$meanTreeHtDomBAW <-
97+
round(stats::weighted.mean(tree_ht_doms, basal_area_doms,
98+
na.rm = TRUE),
99+
digits = digits)
100+
101+
ht_metrics$maxTreeHt <- max(tree_ht, na.rm = TRUE)
102+
103+
tree_ht_tpa <-
104+
data.frame(tree_ht, trees_in$TPA_UNADJ, check.names = FALSE)
105+
tree_ht_tpa <- tree_ht_tpa[order(tree_ht, decreasing = TRUE), ]
106+
tpa <- sum_ht <- n <- 0
107+
for (i in seq_len(nrow(tree_ht_tpa))) {
108+
sum_ht <- sum_ht + tree_ht_tpa[i, 1]
109+
tpa <- tpa + tree_ht_tpa[i, 2]
110+
n <- n + 1
111+
if (tpa > 16)
112+
break
113+
}
114+
ht_metrics$predomTreeHt <- round(sum_ht / n, digits = digits)
98115
}
99116

117+
if (nrow(saplings_in) > 0) {
118+
ht_metrics$meanSapHt <-
119+
round(mean(sapling_ht, na.rm = TRUE), digits = digits)
100120

101-
102-
103-
121+
ht_metrics$maxSapHt <- max(sapling_ht, na.rm = TRUE)
122+
}
104123

105124
return(ht_metrics)
106125
}

_pkgdown.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ home:
1414
reference:
1515
- title: Functions
1616
- contents:
17+
- compute_ht_metrics
1718
- load_tree_data
1819
- overlay_crowns
1920
- plot_crowns

man/compute_ht_metrics.Rd

Lines changed: 54 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
test_that("compute_ht_metrics works", {
2+
expected <- vector(mode = "list", length = 8)
3+
names(expected) <- c("meanTreeHt", "meanTreeHtBAW", "meanTreeHtDom",
4+
"meanTreeHtDomBAW", "maxTreeHt", "predomTreeHt",
5+
"meanSapHt", "maxSapHt")
6+
expected$meanTreeHt <- 45
7+
expected$meanTreeHtBAW <- 45.4
8+
expected$meanTreeHtDom <- 45
9+
expected$meanTreeHtDomBAW <- 45.4
10+
expected$maxTreeHt <- 51
11+
expected$predomTreeHt <- 50.3
12+
expected$meanSapHt <- 33.5
13+
expected$maxSapHt <- 42
14+
expect_equal(compute_ht_metrics(plantation), expected, tolerance = 0.1)
15+
})

0 commit comments

Comments
 (0)