Skip to contents

Methods for using the emmeans package with sdmTMB. The emmeans package computes estimated marginal means for the fixed effects.

Examples

mesh <- make_mesh(pcod_2011, c("X", "Y"), cutoff = 20)
fit <- sdmTMB(
  present ~ as.factor(year),
  data = pcod_2011, mesh = mesh,
  family = binomial()
)
fit
#> Spatial model fit by ML ['sdmTMB']
#> Formula: present ~ as.factor(year)
#> Mesh: mesh (isotropic covariance)
#> Data: pcod_2011
#> Family: binomial(link = 'logit')
#>  
#>                     coef.est coef.se
#> (Intercept)            -0.61    0.55
#> as.factor(year)2013     0.99    0.22
#> as.factor(year)2015     0.75    0.22
#> as.factor(year)2017     0.01    0.22
#> 
#> Matérn range: 48.45
#> Spatial SD: 1.84
#> ML criterion at convergence: 564.495
#> 
#> See ?tidy.sdmTMB to extract these values as a data frame.
emmeans::emmeans(fit, ~ year)
#>  year emmean    SE  df lower.CL upper.CL
#>  2011 -0.606 0.551 963   -1.688    0.475
#>  2013  0.384 0.550 963   -0.695    1.463
#>  2015  0.143 0.551 963   -0.937    1.224
#>  2017 -0.594 0.551 963   -1.674    0.487
#> 
#> Results are given on the logit (not the response) scale. 
#> Confidence level used: 0.95 
emmeans::emmeans(fit, pairwise ~ year)
#> $emmeans
#>  year emmean    SE  df lower.CL upper.CL
#>  2011 -0.606 0.551 963   -1.688    0.475
#>  2013  0.384 0.550 963   -0.695    1.463
#>  2015  0.143 0.551 963   -0.937    1.224
#>  2017 -0.594 0.551 963   -1.674    0.487
#> 
#> Results are given on the logit (not the response) scale. 
#> Confidence level used: 0.95 
#> 
#> $contrasts
#>  contrast            estimate    SE  df t.ratio p.value
#>  year2011 - year2013  -0.9901 0.222 963  -4.467  0.0001
#>  year2011 - year2015  -0.7496 0.220 963  -3.404  0.0039
#>  year2011 - year2017  -0.0127 0.221 963  -0.057  0.9999
#>  year2013 - year2015   0.2405 0.217 963   1.110  0.6837
#>  year2013 - year2017   0.9774 0.223 963   4.390  0.0001
#>  year2015 - year2017   0.7369 0.222 963   3.320  0.0052
#> 
#> Results are given on the log odds ratio (not the response) scale. 
#> P value adjustment: tukey method for comparing a family of 4 estimates 
#> 
emmeans::emmeans(fit, pairwise ~ year, type = "response")
#> $emmeans
#>  year  prob    SE  df lower.CL upper.CL
#>  2011 0.353 0.126 963    0.156    0.617
#>  2013 0.595 0.133 963    0.333    0.812
#>  2015 0.536 0.137 963    0.281    0.773
#>  2017 0.356 0.126 963    0.158    0.619
#> 
#> Confidence level used: 0.95 
#> Intervals are back-transformed from the logit scale 
#> 
#> $contrasts
#>  contrast            odds.ratio     SE  df null t.ratio p.value
#>  year2011 / year2013      0.372 0.0823 963    1  -4.467  0.0001
#>  year2011 / year2015      0.473 0.1041 963    1  -3.404  0.0039
#>  year2011 / year2017      0.987 0.2182 963    1  -0.057  0.9999
#>  year2013 / year2015      1.272 0.2757 963    1   1.110  0.6837
#>  year2013 / year2017      2.658 0.5917 963    1   4.390  0.0001
#>  year2015 / year2017      2.089 0.4638 963    1   3.320  0.0052
#> 
#> P value adjustment: tukey method for comparing a family of 4 estimates 
#> Tests are performed on the log odds ratio scale 
#> 
emmeans::emmeans(fit, pairwise ~ year, adjust = "none")
#> $emmeans
#>  year emmean    SE  df lower.CL upper.CL
#>  2011 -0.606 0.551 963   -1.688    0.475
#>  2013  0.384 0.550 963   -0.695    1.463
#>  2015  0.143 0.551 963   -0.937    1.224
#>  2017 -0.594 0.551 963   -1.674    0.487
#> 
#> Results are given on the logit (not the response) scale. 
#> Confidence level used: 0.95 
#> 
#> $contrasts
#>  contrast            estimate    SE  df t.ratio p.value
#>  year2011 - year2013  -0.9901 0.222 963  -4.467  <.0001
#>  year2011 - year2015  -0.7496 0.220 963  -3.404  0.0007
#>  year2011 - year2017  -0.0127 0.221 963  -0.057  0.9543
#>  year2013 - year2015   0.2405 0.217 963   1.110  0.2675
#>  year2013 - year2017   0.9774 0.223 963   4.390  <.0001
#>  year2015 - year2017   0.7369 0.222 963   3.320  0.0009
#> 
#> Results are given on the log odds ratio (not the response) scale. 
#> 

e <- emmeans::emmeans(fit, ~ year)
plot(e)


e <- emmeans::emmeans(fit, pairwise ~ year)
confint(e)
#> $emmeans
#>  year emmean    SE  df lower.CL upper.CL
#>  2011 -0.606 0.551 963   -1.688    0.475
#>  2013  0.384 0.550 963   -0.695    1.463
#>  2015  0.143 0.551 963   -0.937    1.224
#>  2017 -0.594 0.551 963   -1.674    0.487
#> 
#> Results are given on the logit (not the response) scale. 
#> Confidence level used: 0.95 
#> 
#> $contrasts
#>  contrast            estimate    SE  df lower.CL upper.CL
#>  year2011 - year2013  -0.9901 0.222 963   -1.560   -0.420
#>  year2011 - year2015  -0.7496 0.220 963   -1.316   -0.183
#>  year2011 - year2017  -0.0127 0.221 963   -0.581    0.556
#>  year2013 - year2015   0.2405 0.217 963   -0.317    0.798
#>  year2013 - year2017   0.9774 0.223 963    0.404    1.550
#>  year2015 - year2017   0.7369 0.222 963    0.166    1.308
#> 
#> Results are given on the log odds ratio (not the response) scale. 
#> Confidence level used: 0.95 
#> Conf-level adjustment: tukey method for comparing a family of 4 estimates 
#> 
summary(e, infer = TRUE)
#> $emmeans
#>  year emmean    SE  df lower.CL upper.CL t.ratio p.value
#>  2011 -0.606 0.551 963   -1.688    0.475  -1.100  0.2715
#>  2013  0.384 0.550 963   -0.695    1.463   0.698  0.4854
#>  2015  0.143 0.551 963   -0.937    1.224   0.260  0.7948
#>  2017 -0.594 0.551 963   -1.674    0.487  -1.078  0.2812
#> 
#> Results are given on the logit (not the response) scale. 
#> Confidence level used: 0.95 
#> 
#> $contrasts
#>  contrast            estimate    SE  df lower.CL upper.CL t.ratio p.value
#>  year2011 - year2013  -0.9901 0.222 963   -1.560   -0.420  -4.467  0.0001
#>  year2011 - year2015  -0.7496 0.220 963   -1.316   -0.183  -3.404  0.0039
#>  year2011 - year2017  -0.0127 0.221 963   -0.581    0.556  -0.057  0.9999
#>  year2013 - year2015   0.2405 0.217 963   -0.317    0.798   1.110  0.6837
#>  year2013 - year2017   0.9774 0.223 963    0.404    1.550   4.390  0.0001
#>  year2015 - year2017   0.7369 0.222 963    0.166    1.308   3.320  0.0052
#> 
#> Results are given on the log odds ratio (not the response) scale. 
#> Confidence level used: 0.95 
#> Conf-level adjustment: tukey method for comparing a family of 4 estimates 
#> P value adjustment: tukey method for comparing a family of 4 estimates 
#> 
as.data.frame(e)
#> Warning: Note: 'as.data.frame' has combined your 2 sets of results into one object,
#> and this affects things like adjusted P values. Refer to the annotations.
#>  year contrast                emmean        SE  df   lower.CL   upper.CL
#>  2011 .                   -0.6063952 0.5511170 963 -2.1569729  0.9441824
#>  2013 .                    0.3836816 0.5497815 963 -1.1631386  1.9305018
#>  2015 .                    0.1431957 0.5505275 963 -1.4057236  1.6921150
#>  2017 .                   -0.5937169 0.5506319 963 -2.1429298  0.9554960
#>  .    year2011 - year2013 -0.9900768 0.2216228 963 -1.6136166 -0.3665369
#>  .    year2011 - year2015 -0.7495909 0.2201979 963 -1.3691217 -0.1300601
#>  .    year2011 - year2017 -0.0126783 0.2209364 963 -0.6342868  0.6089302
#>  .    year2013 - year2015  0.2404859 0.2167459 963 -0.3693327  0.8503044
#>  .    year2013 - year2017  0.9773985 0.2226493 963  0.3509706  1.6038264
#>  .    year2015 - year2017  0.7369126 0.2219749 963  0.1123823  1.3614430
#> 
#> Results are given on the logit (not the response) scale. 
#> Confidence level used: 0.95 
#> Conf-level adjustment: bonferroni method for 10 estimates 

# interaction of factor with continuous predictor:
fit2 <- sdmTMB(
  present ~ depth_scaled * as.factor(year),
  data = pcod_2011, mesh = mesh,
  family = binomial()
)
fit2
#> Spatial model fit by ML ['sdmTMB']
#> Formula: present ~ depth_scaled * as.factor(year)
#> Mesh: mesh (isotropic covariance)
#> Data: pcod_2011
#> Family: binomial(link = 'logit')
#>  
#>                                  coef.est coef.se
#> (Intercept)                         -0.75    0.48
#> depth_scaled                        -0.98    0.25
#> as.factor(year)2013                  1.03    0.23
#> as.factor(year)2015                  0.79    0.23
#> as.factor(year)2017                  0.01    0.23
#> depth_scaled:as.factor(year)2013    -0.16    0.26
#> depth_scaled:as.factor(year)2015     0.03    0.26
#> depth_scaled:as.factor(year)2017    -0.01    0.26
#> 
#> Matérn range: 33.38
#> Spatial SD: 2.19
#> ML criterion at convergence: 546.074
#> 
#> See ?tidy.sdmTMB to extract these values as a data frame.
# slopes for each level:
emmeans::emtrends(fit2, ~ year, var = "depth_scaled")
#>  year depth_scaled.trend    SE  df lower.CL upper.CL
#>  2011             -0.980 0.250 959    -1.47   -0.490
#>  2013             -1.140 0.247 959    -1.63   -0.655
#>  2015             -0.950 0.238 959    -1.42   -0.483
#>  2017             -0.987 0.244 959    -1.47   -0.507
#> 
#> Confidence level used: 0.95 
# test difference in slopes:
emmeans::emtrends(fit2, pairwise ~ year, var = "depth_scaled")
#> $emtrends
#>  year depth_scaled.trend    SE  df lower.CL upper.CL
#>  2011             -0.980 0.250 959    -1.47   -0.490
#>  2013             -1.140 0.247 959    -1.63   -0.655
#>  2015             -0.950 0.238 959    -1.42   -0.483
#>  2017             -0.987 0.244 959    -1.47   -0.507
#> 
#> Confidence level used: 0.95 
#> 
#> $contrasts
#>  contrast            estimate    SE  df t.ratio p.value
#>  year2011 - year2013  0.16009 0.261 959   0.613  0.9281
#>  year2011 - year2015 -0.03052 0.265 959  -0.115  0.9995
#>  year2011 - year2017  0.00651 0.261 959   0.025  1.0000
#>  year2013 - year2015 -0.19061 0.258 959  -0.738  0.8817
#>  year2013 - year2017 -0.15358 0.259 959  -0.593  0.9342
#>  year2015 - year2017  0.03703 0.263 959   0.141  0.9990
#> 
#> P value adjustment: tukey method for comparing a family of 4 estimates 
#> 
emmeans::emmip(fit2, year ~ depth_scaled,
  at = list(depth_scaled = seq(-2.5, 2.5, length.out = 50)), CIs = TRUE)