The statistical model:
\(y_t = \beta_0 + \beta_1 * (Elevation_s)_t + \beta_2 * Slope_t + (b_s)_t + \epsilon_t\)
Where:
Let’s define the parameters:
nstand = 5
nplot = 4
b0 = -1
b1 = .005
b2 = .1
sds = 2
sd = 1
Simulate other variables:
set.seed(16)
stand = rep(LETTERS[1:nstand], each = nplot)
standeff = rep( rnorm(nstand, 0, sds), each = nplot)
ploteff = rnorm(nstand*nplot, 0, sd)
Simulate elevation and slope:
elevation = rep( runif(nstand, 1000, 1500), each = nplot)
slope = runif(nstand*nplot, 2, 75)
Simulate response variable:
resp2 = b0 + b1*elevation + b2*slope + standeff + ploteff
Your tasks (complete each task in its’ own code chunk, make sure to use echo=TRUE so I can see your code):
library(lme4)
## Warning: package 'lme4' was built under R version 3.6.1
## Loading required package: Matrix
library(lmerTest)
## Warning: package 'lmerTest' was built under R version 3.6.1
##
## Attaching package: 'lmerTest'
## The following object is masked from 'package:lme4':
##
## lmer
## The following object is masked from 'package:stats':
##
## step
fit_model <- lmer(resp2 ~ 1 + elevation + slope + (1|stand))
summary(fit_model)
## Linear mixed model fit by REML. t-tests use Satterthwaite's method [
## lmerModLmerTest]
## Formula: resp2 ~ 1 + elevation + slope + (1 | stand)
##
## REML criterion at convergence: 82
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -1.65583 -0.62467 -0.01693 0.53669 1.41736
##
## Random effects:
## Groups Name Variance Std.Dev.
## stand (Intercept) 1.208 1.099
## Residual 1.358 1.165
## Number of obs: 20, groups: stand, 5
##
## Fixed effects:
## Estimate Std. Error df t value Pr(>|t|)
## (Intercept) -21.314628 6.602053 3.001313 -3.228 0.0482 *
## elevation 0.020600 0.004916 3.113482 4.190 0.0230 *
## slope 0.095105 0.016441 15.868032 5.785 2.88e-05 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) elevtn
## elevation -0.991
## slope 0.049 -0.148
cat("b0 = ", b0, sep = "")
## b0 = -1
cat("b1 = ", b1, sep = "")
## b1 = 0.005
cat("b2 = ", b2, sep = "")
## b2 = 0.1
Defined intercept(b0) is -1 (Completely different compared to estimated intercept -21.314628) Defined Elevation(b1) is 0.005 (smaller compared to estimated elevation 0.020600) Defined slope(b1) is 0.1 (very close to estimated slope of 0.095105)
simulation_m <- function(nstand = 5, nplot = 4, b0 = -1, b1 = 0.005, b2 = 0.1, sds = 2, sd = 1) {
stand <- rep(LETTERS[1:nstand], each = nplot)
standeff <- rep(rnorm(nstand, 0, sds), each = nplot)
ploteff <- rnorm(nstand * nplot, 0, sd)
elevation <- rep(runif(nstand, 1000, 1500), each = nplot)
slope <- runif(nstand * nplot, 2, 75)
resp2 <- b0 + b1 * elevation + b2 * slope + standeff + ploteff
data_f <- data.frame(resp2, elevation, slope, stand)
lmer(resp2 ~ 1 + elevation + slope + (1|stand), data = data_f)
}
simulation_m()
## Linear mixed model fit by REML ['lmerModLmerTest']
## Formula: resp2 ~ 1 + elevation + slope + (1 | stand)
## Data: data_f
## REML criterion at convergence: 80.9781
## Random effects:
## Groups Name Std.Dev.
## stand (Intercept) 2.3573
## Residual 0.9754
## Number of obs: 20, groups: stand, 5
## Fixed Effects:
## (Intercept) elevation slope
## 10.584601 -0.005464 0.086839
simulation_result <- replicate(n = 1000, expr = simulation_m())
## boundary (singular) fit: see ?isSingular
## boundary (singular) fit: see ?isSingular
## boundary (singular) fit: see ?isSingular
## boundary (singular) fit: see ?isSingular
## Warning in checkConv(attr(opt, "derivs"), opt$par, ctrl =
## control$checkConv, : Model failed to converge with max|grad| = 0.00350336
## (tol = 0.002, component 1)
## Warning in checkConv(attr(opt, "derivs"), opt$par, ctrl =
## control$checkConv, : Model failed to converge with max|grad| = 0.0045514
## (tol = 0.002, component 1)
## boundary (singular) fit: see ?isSingular
## boundary (singular) fit: see ?isSingular
## boundary (singular) fit: see ?isSingular
## boundary (singular) fit: see ?isSingular
## Warning in checkConv(attr(opt, "derivs"), opt$par, ctrl =
## control$checkConv, : Model failed to converge with max|grad| = 0.00363544
## (tol = 0.002, component 1)
## boundary (singular) fit: see ?isSingular
## Warning in checkConv(attr(opt, "derivs"), opt$par, ctrl =
## control$checkConv, : Model failed to converge with max|grad| = 0.00439561
## (tol = 0.002, component 1)
## Warning in checkConv(attr(opt, "derivs"), opt$par, ctrl =
## control$checkConv, : Model failed to converge with max|grad| = 0.00239513
## (tol = 0.002, component 1)
## Warning in checkConv(attr(opt, "derivs"), opt$par, ctrl =
## control$checkConv, : Model failed to converge with max|grad| = 0.00219495
## (tol = 0.002, component 1)
## boundary (singular) fit: see ?isSingular
## boundary (singular) fit: see ?isSingular
## boundary (singular) fit: see ?isSingular
## Warning in checkConv(attr(opt, "derivs"), opt$par, ctrl =
## control$checkConv, : Model failed to converge with max|grad| = 0.00322495
## (tol = 0.002, component 1)
## boundary (singular) fit: see ?isSingular
length(simulation_result)
## [1] 1000
library(tidyverse)
## Warning: package 'tidyverse' was built under R version 3.6.1
## -- Attaching packages ---------------------------------------- tidyverse 1.2.1 --
## v ggplot2 3.2.1 v purrr 0.3.2
## v tibble 2.1.3 v dplyr 0.8.3
## v tidyr 0.8.3 v stringr 1.4.0
## v readr 1.3.1 v forcats 0.4.0
## Warning: package 'ggplot2' was built under R version 3.6.1
## Warning: package 'tidyr' was built under R version 3.6.1
## Warning: package 'readr' was built under R version 3.6.1
## Warning: package 'purrr' was built under R version 3.6.1
## Warning: package 'dplyr' was built under R version 3.6.1
## Warning: package 'stringr' was built under R version 3.6.1
## Warning: package 'forcats' was built under R version 3.6.1
## -- Conflicts ------------------------------------------- tidyverse_conflicts() --
## x tidyr::expand() masks Matrix::expand()
## x dplyr::filter() masks stats::filter()
## x dplyr::lag() masks stats::lag()
library(broom)
## Warning: package 'broom' was built under R version 3.6.1
library(broom.mixed)
## Warning: package 'broom.mixed' was built under R version 3.6.1
## Registered S3 methods overwritten by 'broom.mixed':
## method from
## augment.lme broom
## augment.merMod broom
## glance.lme broom
## glance.merMod broom
## glance.stanreg broom
## tidy.brmsfit broom
## tidy.gamlss broom
## tidy.lme broom
## tidy.merMod broom
## tidy.rjags broom
## tidy.stanfit broom
## tidy.stanreg broom
##
## Attaching package: 'broom.mixed'
## The following object is masked from 'package:broom':
##
## tidyMCMC
variances <- simulation_result %>% map_dfr(tidy, effects = "ran_pars", scales = "vcov")
head(variances,6)
## # A tibble: 6 x 4
## effect group term estimate
## <chr> <chr> <chr> <dbl>
## 1 ran_pars stand var__(Intercept) 2.61
## 2 ran_pars Residual var__Observation 1.11
## 3 ran_pars stand var__(Intercept) 9.73
## 4 ran_pars Residual var__Observation 1.36
## 5 ran_pars stand var__(Intercept) 0.827
## 6 ran_pars Residual var__Observation 0.914
library(ggplot2)
library(furrr)
## Warning: package 'furrr' was built under R version 3.6.1
## Loading required package: future
## Warning: package 'future' was built under R version 3.6.1
plan(multiprocess)
simulation_l_3 <- c(20, 60, 150) %>%
set_names(c("size_20", "size_60", "size_150")) %>%
map(function(.size) replicate(n = 1000, expr = simulation_m(nstand = .size)))
## Warning in checkConv(attr(opt, "derivs"), opt$par, ctrl =
## control$checkConv, : Model failed to converge with max|grad| = 0.0023312
## (tol = 0.002, component 1)
## Warning in checkConv(attr(opt, "derivs"), opt$par, ctrl =
## control$checkConv, : Model failed to converge with max|grad| = 0.0149742
## (tol = 0.002, component 1)
## Warning in checkConv(attr(opt, "derivs"), opt$par, ctrl =
## control$checkConv, : Model failed to converge with max|grad| = 0.00215173
## (tol = 0.002, component 1)
## Warning in checkConv(attr(opt, "derivs"), opt$par, ctrl =
## control$checkConv, : Model failed to converge with max|grad| = 0.00201316
## (tol = 0.002, component 1)
## Warning in checkConv(attr(opt, "derivs"), opt$par, ctrl =
## control$checkConv, : Model failed to converge with max|grad| = 0.00201341
## (tol = 0.002, component 1)
simulation_df <- simulation_l_3 %>%
modify_depth(.depth = 2, function(x) tidy(x, effects = "ran_pars", scales = "vcov")) %>%
map_dfr(bind_rows, .id = "id") %>%
filter(group == "stand")
simulation_df
## # A tibble: 3,000 x 5
## id effect group term estimate
## <chr> <chr> <chr> <chr> <dbl>
## 1 size_20 ran_pars stand var__(Intercept) 3.41
## 2 size_20 ran_pars stand var__(Intercept) 3.52
## 3 size_20 ran_pars stand var__(Intercept) 2.67
## 4 size_20 ran_pars stand var__(Intercept) 3.54
## 5 size_20 ran_pars stand var__(Intercept) 3.36
## 6 size_20 ran_pars stand var__(Intercept) 2.87
## 7 size_20 ran_pars stand var__(Intercept) 5.45
## 8 size_20 ran_pars stand var__(Intercept) 3.91
## 9 size_20 ran_pars stand var__(Intercept) 3.52
## 10 size_20 ran_pars stand var__(Intercept) 2.31
## # ... with 2,990 more rows
simulation_df %>%
mutate(
id = case_when(
id == "size_20" ~ "size = 20",
id == "size_60" ~ "size = 60",
id == "size_150" ~ "size = 150"
)
) %>%
ggplot(aes(x = estimate) ) +
geom_density(fill = "green", alpha = .25) +
facet_wrap(~ id) +
geom_vline(xintercept = 4) +
theme_bw()
The plot shows that the estimate is more accurate when the sample size surges.
library(furrr)
library(magrittr)
##
## Attaching package: 'magrittr'
## The following object is masked from 'package:purrr':
##
## set_names
## The following object is masked from 'package:tidyr':
##
## extract
library(dplyr)
library(broom)
library(broom.mixed)
library(ggplot2)
simulation_es <- simulation_result %>%
map(tidy, effects = "fixed") %>%
bind_rows()
simulation_es
## # A tibble: 3,000 x 7
## effect term estimate std.error statistic df p.value
## <chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 fixed (Intercept) -15.9 5.63 -2.83 2.99 0.0661
## 2 fixed elevation 0.0152 0.00426 3.57 2.99 0.0377
## 3 fixed slope 0.121 0.0157 7.73 15.5 0.00000107
## 4 fixed (Intercept) -13.9 13.3 -1.05 3.00 0.372
## 5 fixed elevation 0.0156 0.0117 1.33 2.99 0.276
## 6 fixed slope 0.124 0.0166 7.48 14.3 0.00000257
## 7 fixed (Intercept) -12.3 4.45 -2.75 2.92 0.0729
## 8 fixed elevation 0.0130 0.00336 3.87 3.01 0.0304
## 9 fixed slope 0.0937 0.0100 9.32 14.7 0.000000151
## 10 fixed (Intercept) -11.9 21.4 -0.556 3.06 0.616
## # ... with 2,990 more rows
simulation_es %>%
dplyr::filter(term %in% c("elevation", "slope")) %>%
group_by(term) %>%
mutate(x = 1:1000) %>%
ungroup() %>%
mutate(real_value = ifelse(term == "elevation", 0.005, 0.1)) %>%
ggplot(aes(x = x, y = estimate)) +
geom_line() +
facet_wrap(~ term) +
geom_hline(aes(yintercept = real_value, color = term), linetype = 2, size = 0.8) +
theme_bw()
It shows estimates of elevation and slope are move in a wave-like pattern.