Process and Measurement error in a simple growth process.
UdeS
stan
Author
Will Vieira, Andrew MacDonald
Published
November 11, 2022
The following is a simulation by Will Vieira which explores how process uncertainty and measurement error combine when we measure trees.
The model imagines a simple linear growth scenario: every year, individuals grow by a random amount \(g_i\). This growth increment is random and varies each year according to a normal distribution
\[
\begin{align}
L_{\text{year}[i]} \sim N \\
\end{align}
\]
\[
L = lo
\]
Here is Will’s very clean and concise simulation code.
library(ggplot2)library(tidyverse)set.seed(0.0)nbInd <-2000deltaYear =14obsError =5# Generate individual trees with random size in mmsizeGrowth_dt <-tibble(tree_id =1:nbInd,size_real0 =rgamma(nbInd, 190^2/1e4, 190/1e4) ) |># each indv increment every year with a N(2.3, 2.2) (values from dataset);# here from size_t to size_t+1 is the sum of X years growthmutate(size_real1 = size_real0 +replicate(n(), sum(rnorm(deltaYear, 2.3, 2.2))),size_real2 = size_real1 +replicate(n(), sum(rnorm(deltaYear, 2.3, 2.2))),size_real3 = size_real2 +replicate(n(), sum(rnorm(deltaYear, 2.3, 2.2))),size_real4 = size_real3 +replicate(n(), sum(rnorm(deltaYear, 2.3, 2.2))) ) |>pivot_longer(cols =contains('size'),names_to ='timeStep',values_to ='size_real' ) |># each observation has an error of measurementmutate(size_random =rnorm(n(), mean = size_real, sd = obsError) ) |># calculate growth from real and random (observed) valuesgroup_by(tree_id) |>mutate(growth_real = (size_real -lag(size_real, 1))/deltaYear,growth_random = (size_random -lag(size_random, 1))/deltaYear ) |>ungroup() |>pivot_longer(cols =contains(c('real', 'random')),names_to =c('var', 'type'),names_sep ='_' ) |># remove NA for first time stepfilter(!is.na(value))p1 <- sizeGrowth_dt |>pivot_wider(names_from = type,values_from = value ) |>ggplot(aes(x = real, y = random)) +geom_point(size = .5) +facet_wrap(~var, scales ='free') +geom_abline(intercept =0, slope =1)p2 <- sizeGrowth_dt |>ggplot(aes(value, color = type)) +geom_density() +facet_wrap(~var, scales ='free')library(patchwork)p1 + p2