The hardware and bandwidth for this mirror is donated by dogado GmbH, the Webhosting and Full Service-Cloud Provider. Check out our Wordpress Tutorial.
If you wish to report a bug, or if you are interested in having us mirror your free-software or open-source project, please feel free to contact us at mirror[@]dogado.de.

Neighborhood basal area with calba

This vignette shows how to compute neighborhood basal area with calba. We start from a simple simulated plot, then use neigh_ba() for model-ready summaries. We then illustrate multiple radii, low-level helper functions, and basic edge correction options.

Example data

Simulate a modest plot with 500 trees, four species, 50x50 m extent, and basal areas between 20 and 200 (e.g., cm^2).

library(calba)
library(ggplot2)
set.seed(42)
side <- 50
n <- 500
trees <- data.frame(
  species = sample(c("oak", "pine", "birch", "maple"), n, replace = TRUE),
  gx = runif(n, 0, side),
  gy = runif(n, 0, side),
  ba = runif(n, 20, 200)
)

ggplot(trees, aes(gx, gy, col = species)) +
  geom_point() +
  coord_fixed() +
  theme_bw()

Core summaries: neigh_ba()

neigh_ba() computes conspecific and total basal area, neighbor counts, and derived metrics for a single radius.

Optionally, we can add decay-weighted summaries by supplying mu_values. This appends a long table of distance-weighted basal area for each decay parameter, which is returned in the decay component.

nb <- neigh_ba(
  sp = trees$species,
  gx = trees$gx,
  gy = trees$gy,
  ba = trees$ba,
  r = 5,
  mu_values = c(2, 6)
)

head(nb$summary)
##   tree_id species   con_ba total_ba con_count total_count prop_con_ba    het_ba
## 1       1     oak 551.5438 2539.628         4          19   0.2171751 1988.0838
## 2       2     oak 232.2601 1534.218         3          14   0.1513866 1301.9581
## 3       3     oak 592.0395 1105.628         6          12   0.5354780  513.5886
## 4       4     oak 509.0855 1245.698         6          12   0.4086749  736.6124
## 5       5    pine 601.2436 2226.411         5          19   0.2700506 1625.1673
## 6       6   maple 394.3903 1969.297         4          17   0.2002696 1574.9068
##   het_count competition_index
## 1        15         133.66461
## 2        11         109.58701
## 3         6          92.13568
## 4         6         103.80816
## 5        14         117.17952
## 6        13         115.84101

We can inspect the full structure of the returned object:

str(nb)
## List of 2
##  $ summary:'data.frame': 500 obs. of  10 variables:
##   ..$ tree_id          : int [1:500] 1 2 3 4 5 6 7 8 9 10 ...
##   ..$ species          : chr [1:500] "oak" "oak" "oak" "oak" ...
##   ..$ con_ba           : num [1:500] 552 232 592 509 601 ...
##   ..$ total_ba         : num [1:500] 2540 1534 1106 1246 2226 ...
##   ..$ con_count        : num [1:500] 4 3 6 6 5 4 6 8 1 1 ...
##   ..$ total_count      : num [1:500] 19 14 12 12 19 17 19 23 9 17 ...
##   ..$ prop_con_ba      : num [1:500] 0.217 0.151 0.535 0.409 0.27 ...
##   ..$ het_ba           : num [1:500] 1988 1302 514 737 1625 ...
##   ..$ het_count        : num [1:500] 15 11 6 6 14 13 13 15 8 16 ...
##   ..$ competition_index: num [1:500] 133.7 109.6 92.1 103.8 117.2 ...
##  $ decay  :'data.frame': 1000 obs. of  5 variables:
##   ..$ tree_id : int [1:1000] 1 2 3 4 5 6 7 8 9 10 ...
##   ..$ species : chr [1:1000] "oak" "oak" "oak" "oak" ...
##   ..$ mu      : num [1:1000] 2 2 2 2 2 2 2 2 2 2 ...
##   ..$ con_ba  : num [1:1000] 157.6 61.1 88.1 102.4 115.8 ...
##   ..$ total_ba: num [1:1000] 692 554 180 204 381 ...

nb$decay is a long table of decay-weighted basal area for each mu.

head(nb$decay)
##   tree_id species mu    con_ba total_ba
## 1       1     oak  2 157.61987 692.3895
## 2       2     oak  2  61.13062 554.2654
## 3       3     oak  2  88.08783 180.0602
## 4       4     oak  2 102.40837 203.6150
## 5       5    pine  2 115.84979 380.6603
## 6       6   maple  2  62.66209 491.2417

Edge handling and bounds

Use edge_correction = "safe" to return NA for focal trees within r of the plot boundary. By default, bounds are the min and max of gx and gy. Supply bounds = c(xmin, xmax, ymin, ymax) if your plot is larger than the observed coordinates.

nb_bounds <- neigh_ba(
  sp = trees$species,
  gx = trees$gx,
  gy = trees$gy,
  ba = trees$ba,
  r = 5,
  edge_correction = "safe",
  bounds = c(0, 50, 0, 50)
)$summary

head(nb_bounds)
##   tree_id species   con_ba total_ba con_count total_count prop_con_ba    het_ba
## 1       1     oak 551.5438 2539.628         4          19   0.2171751 1988.0838
## 2       2     oak       NA       NA        NA          NA          NA        NA
## 3       3     oak 592.0395 1105.628         6          12   0.5354780  513.5886
## 4       4     oak 509.0855 1245.698         6          12   0.4086749  736.6124
## 5       5    pine 601.2436 2226.411         5          19   0.2700506 1625.1673
## 6       6   maple       NA       NA        NA          NA          NA        NA
##   het_count competition_index
## 1        15         133.66461
## 2        NA                NA
## 3         6          92.13568
## 4         6         103.80816
## 5        14         117.17952
## 6        NA                NA

Then in Low-level helpers you keep the detailed explanation of the exponential and exponential-normal kernels and the ba_decay() code.

Multiple radii in one pass: neigh_multi_r()

Reuse a single distance structure across radii.

multi <- neigh_multi_r(
  sp = trees$species,
  gx = trees$gx,
  gy = trees$gy,
  ba = trees$ba,
  r_values = c(3, 5, 10),
  dist_weighted = FALSE
)

multi_r5 <- subset(multi, radius == 5)
head(multi_r5)
##     tree_id species radius   con_ba total_ba con_count total_count prop_con_ba
## 501       1     oak      5 551.5438 2539.628         4          19   0.2171751
## 502       2     oak      5 232.2601 1534.218         3          14   0.1513866
## 503       3     oak      5 592.0395 1105.628         6          12   0.5354780
## 504       4     oak      5 509.0855 1245.698         6          12   0.4086749
## 505       5    pine      5 601.2436 2226.411         5          19   0.2700506
## 506       6   maple      5 394.3903 1969.297         4          17   0.2002696
##        het_ba het_count competition_index
## 501 1988.0838        15         133.66461
## 502 1301.9581        11         109.58701
## 503  513.5886         6          92.13568
## 504  736.6124         6         103.80816
## 505 1625.1673        14         117.17952
## 506 1574.9068        13         115.84101

Low-level helpers

calba provides several lower-level functions used by neigh_ba() and neigh_multi_r():

Decay kernels in ba_decay()

ba_decay() computes distance–weighted basal area using either of two kernels.

Exponential:

\[ w(d, \mu) = \exp\left(-\frac{d}{\mu}\right) \]

Exponential-normal (Gaussian in distance):

\[ w(d, \mu) = \exp\left(-\frac{d^2}{\mu^2}\right) \]

Neighbors contribute ba * w(d, mu) to the focal tree, where d is Euclidean distance and mu controls the decay scale.

mu_vals <- c(2, 6)

decay_exp <- ba_decay(
  mu_values = mu_vals,
  sp = trees$species,
  gx = trees$gx,
  gy = trees$gy,
  ba = trees$ba,
  r = 5,
  exponential_normal = FALSE
)
head(decay_exp$con_ba_matrix)
##           [,1]     [,2]
## [1,] 157.61987 334.6172
## [2,]  61.13062 143.7360
## [3,]  88.08783 306.0831
## [4,] 102.40837 281.1512
## [5,] 115.84979 342.8400
## [6,]  62.66209 210.8749
decay_expnorm <- ba_decay(
  mu_values = mu_vals,
  sp = trees$species,
  gx = trees$gx,
  gy = trees$gy,
  ba = trees$ba,
  r = 5,
  exponential_normal = TRUE
)
head(decay_expnorm$con_ba_matrix)
##           [,1]     [,2]
## [1,] 141.78479 394.8385
## [2,]  52.13371 177.6364
## [3,]  30.15202 375.5627
## [4,]  77.55324 338.8034
## [5,]  52.24974 433.3304
## [6,]  19.18204 263.5829

Unweighted or distance-weighted basal area: ba_simple()

ba_simple_out <- ba_simple(
  sp = trees$species,
  gx = trees$gx,
  gy = trees$gy,
  ba = trees$ba,
  r = 5,
  dist_weighted = TRUE
)

str(ba_simple_out)
## List of 2
##  $ con_ba  : num [1:500] 315.2 91.1 156 169.9 184.3 ...
##  $ total_ba: num [1:500] 1328 1224 307 356 668 ...

Neighbor counts

count_total_out <- count_total(trees$gx, trees$gy, r = 5)
head(count_total_out)
## [1] 19 14 12 12 19 17

These binaries (installable software) and packages are in development.
They may not be fully stable and should be used with caution. We make no claims about them.
Health stats visible at Monitor.