R package gllvm fits Generalized linear latent variable models (GLLVM) for multivariate data1.
Developed by J. Niku, W.Brooks, R. Herliansyah, F.K.C. Hui, S. Taskinen, D.I. Warton, B. van der Veen.
The package available in
Package installation:
# From CRAN
install.packages(gllvm)
# OR
# From GitHub using devtools package's function install_github
devtools::install_github("JenniNiku/gllvm")
gllvm package depends on R packages TMB and mvabund, try to install these first.
GLLVMs are computationally intensive to fit due the integral in log-likelihood.
gllvm package overcomes computational problems by applying closed form approximations to log-likelihood and using automatic differentiation in C++ to accelerate computation times (TMB2).
Estimation is performed using either variational approximation (VA3), extended variational approximation method (EVA4) or Laplace approximation (LA5) method implemented via R package TMB.
VA method is faster and more accurate than LA, but not applicable for all distributions and link functions.
Using gllvm we can fit
Additional tools: model checking, model selection, inference, visualization.
Response | Distribution | Method | Link |
---|---|---|---|
Counts | Poisson | VA/LA | log |
NB | VA/LA | log | |
ZIP | LA | log | |
Binary | Bernoulli | VA/LA | probit |
EVA/LA | logit | ||
Ordinal | Ordinal | VA | probit |
Normal | Gaussian | VA/LA | identity |
Positive continuous | Gamma | VA/LA | log |
Non-negative continuous | Exponential | VA/LA | log |
Biomass | Tweedie | LA/EVA | log |
Percent cover | beta | LA/EVA | probit/logit |
Main function of the gllvm package is
gllvm()
, which can be used to fit GLLVMs for multivariate
data with the most important arguments listed in the following:
gllvm(y = NULL, X = NULL, TR = NULL, family, num.lv = 2,
formula = NULL, method = "VA", row.eff = FALSE, n.init=1, starting.val ="res", ...)
soil.dry
: Soil dry massbare.sand
: cover of bare sandfallen.leaves
: cover of fallen leaves/twigsmoss
: cover of mossherb.layer
: cover of herb layerreflection
: reflection of the soil surface with a
cloudless skyFitting basic GLLVM \(g(E(y_{ij})) = \beta_{0j} + \boldsymbol{u}_i'\boldsymbol{\theta}_j\) with gllvm:
library(mvabund)
data("spider")
library(gllvm)
fitnb <- gllvm(y = spider$abund, family = "negative.binomial", num.lv = 2)
fitnb
## Call:
## gllvm(y = spider$abund, family = "negative.binomial", num.lv = 2)
## family:
## [1] "negative.binomial"
## method:
## [1] "VA"
##
## log-likelihood: -733.6806
## Residual degrees of freedom: 289
## AIC: 1561.361
## AICc: 1577.028
## BIC: 1740.765
Residual analysis can be used to assess the appropriateness of the fitted model (eg. in terms of mean-variance relationship).
Randomized quantile/Dunn-Smyth residuals7 are used in the package, as they provide standard normal distributed residuals, even for discrete responses, in the case of a proper model.
Try to do these exercises for the next 10 minutes, as many as time is enough for.
E1. Load spider data from mvabund package and take a look at the dataset.
library(gllvm)
#Package **mvabund** is loaded with **gllvm** so just load with a function `data()`.
data("spider")
# more info:
# ?spider
1. Print the data and covariates and draw a boxplot of the data.
# response matrix:
spider$abund
## Alopacce Alopcune Alopfabr Arctlute Arctperi Auloalbi Pardlugu Pardmont
## [1,] 25 10 0 0 0 4 0 60
## [2,] 0 2 0 0 0 30 1 1
## [3,] 15 20 2 2 0 9 1 29
## [4,] 2 6 0 1 0 24 1 7
## [5,] 1 20 0 2 0 9 1 2
## [6,] 0 6 0 6 0 6 0 11
## [7,] 2 7 0 12 0 16 1 30
## [8,] 0 11 0 0 0 7 55 2
## [9,] 1 1 0 0 0 0 0 26
## [10,] 3 0 1 0 0 0 0 22
## [11,] 15 1 2 0 0 1 0 95
## [12,] 16 13 0 0 0 0 0 96
## [13,] 3 43 1 2 0 18 1 24
## [14,] 0 2 0 1 0 4 3 14
## [15,] 0 0 0 0 0 0 6 0
## [16,] 0 3 0 0 0 0 6 0
## [17,] 0 0 0 0 0 0 2 0
## [18,] 0 1 0 0 0 0 5 0
## [19,] 0 1 0 0 0 0 12 0
## [20,] 0 2 0 0 0 0 13 0
## [21,] 0 1 0 0 0 0 16 1
## [22,] 7 0 16 0 4 0 0 2
## [23,] 17 0 15 0 7 0 2 6
## [24,] 11 0 20 0 5 0 0 3
## [25,] 9 1 9 0 0 2 1 11
## [26,] 3 0 6 0 18 0 0 0
## [27,] 29 0 11 0 4 0 0 1
## [28,] 15 0 14 0 1 0 0 6
## Pardnigr Pardpull Trocterr Zoraspin
## [1,] 12 45 57 4
## [2,] 15 37 65 9
## [3,] 18 45 66 1
## [4,] 29 94 86 25
## [5,] 135 76 91 17
## [6,] 27 24 63 34
## [7,] 89 105 118 16
## [8,] 2 1 30 3
## [9,] 1 1 2 0
## [10,] 0 0 1 0
## [11,] 0 1 4 0
## [12,] 1 8 13 0
## [13,] 53 72 97 22
## [14,] 15 72 94 32
## [15,] 0 0 25 3
## [16,] 2 0 28 4
## [17,] 0 0 23 2
## [18,] 0 0 25 0
## [19,] 1 0 22 3
## [20,] 0 0 22 2
## [21,] 0 1 18 2
## [22,] 0 0 1 0
## [23,] 0 0 1 0
## [24,] 0 0 0 0
## [25,] 6 0 16 6
## [26,] 0 0 1 0
## [27,] 0 0 0 0
## [28,] 0 0 2 0
# Environmental variables
spider$x
## soil.dry bare.sand fallen.leaves moss herb.layer reflection
## 1 2.3321 0.0000 0.0000 3.0445 4.4543 3.9120
## 2 3.0493 0.0000 1.7918 1.0986 4.5643 1.6094
## 3 2.5572 0.0000 0.0000 2.3979 4.6052 3.6889
## 4 2.6741 0.0000 0.0000 2.3979 4.6151 2.9957
## 5 3.0155 0.0000 0.0000 0.0000 4.6151 2.3026
## 6 3.3810 2.3979 3.4340 2.3979 3.4340 0.6931
## 7 3.1781 0.0000 0.0000 0.6931 4.6151 2.3026
## 8 2.6247 0.0000 4.2627 1.0986 3.4340 0.6931
## 9 2.4849 0.0000 0.0000 4.3307 3.2581 3.4012
## 10 2.1972 3.9318 0.0000 3.4340 3.0445 3.6889
## 11 2.2192 0.0000 0.0000 4.1109 3.7136 3.6889
## 12 2.2925 0.0000 0.0000 3.8286 4.0254 3.6889
## 13 3.5175 1.7918 1.7918 0.6931 4.5109 3.4012
## 14 3.0865 0.0000 0.0000 1.7918 4.5643 1.0986
## 15 3.2696 0.0000 4.3944 0.6931 3.0445 0.6931
## 16 3.0301 0.0000 4.6052 0.6931 0.6931 0.0000
## 17 3.3322 0.0000 4.4543 0.6931 3.0445 1.0986
## 18 3.1224 0.0000 4.3944 0.0000 3.0445 1.0986
## 19 2.9232 0.0000 4.5109 1.6094 1.6094 0.0000
## 20 3.1091 0.0000 4.5951 0.6931 0.6931 0.0000
## 21 2.9755 0.0000 4.5643 0.6931 1.7918 0.0000
## 22 1.2528 3.2581 0.0000 4.3307 0.6931 3.9120
## 23 1.1939 3.0445 0.0000 4.0254 3.2581 4.0943
## 24 1.6487 3.2581 0.0000 4.0254 3.0445 4.0073
## 25 1.8245 3.5835 0.0000 1.0986 4.1109 2.3026
## 26 0.9933 4.5109 0.0000 1.7918 1.7918 4.3820
## 27 0.9555 2.3979 0.0000 3.8286 3.4340 3.6889
## 28 0.9555 3.4340 0.0000 3.7136 3.4340 3.6889
# Plot data using boxplot:
boxplot(spider$abund)
E2. Fit GLLVM to spider data with a suitable distribution. Data consists of counts of spider species.
2. Response variables in spider data are counts, so Poisson, negative binomial and zero inflated Poisson are possible. However, ZIP is implemented only with Laplace method, so it need to be noticed, that if models are fitted with different methods they can not be compared with information criteria. Let’s try just with a Poisson and NB. NOTE THAT the results may not be exactly the same as below, as the initial values for each model fit are slightly different, so the results may also differ slightly.
# Fit a GLLVM to data
fitp <- gllvm(y=spider$abund, family = poisson(), num.lv = 2)
fitp
## Call:
## gllvm(y = spider$abund, family = poisson(), num.lv = 2)
## family:
## [1] "poisson"
## method:
## [1] "VA"
##
## log-likelihood: -845.8277
## Residual degrees of freedom: 301
## AIC: 1761.655
## AICc: 1770.055
## BIC: 1895.254
fitnb <- gllvm(y=spider$abund, family = "negative.binomial", num.lv = 2)
fitnb
## Call:
## gllvm(y = spider$abund, family = "negative.binomial", num.lv = 2)
## family:
## [1] "negative.binomial"
## method:
## [1] "VA"
##
## log-likelihood: -733.6806
## Residual degrees of freedom: 289
## AIC: 1561.361
## AICc: 1577.028
## BIC: 1740.765
Based on AIC, NB distribution suits better. How about residual analysis: NOTE THAT The package uses randomized quantile residuals so each time you plot the residuals, they look a little different.
You could do these comparisons with Laplace method as well, using the code below, and it would give the same conclusion that NB distribution suits best:
E3. Explore the fitted model. Where are the estimates for parameters? What about predicted latent variables? Standard errors?
3. Lets explore the fitted model:
# Parameters:
coef(fitnb)
## $Species.scores
## LV1 LV2
## Alopacce 1.0000000 0.00000000
## Alopcune -0.2631344 1.00000000
## Alopfabr 0.9015719 -0.48406532
## Arctlute -0.7036383 2.03037405
## Arctperi 0.5939406 -1.58944386
## Auloalbi -0.6526883 1.53312316
## Pardlugu -0.8886139 -0.02803668
## Pardmont 0.7498062 0.58843536
## Pardnigr -0.5748640 1.78025969
## Pardpull -0.4146790 1.94808384
## Trocterr -0.4694517 0.78799364
## Zoraspin -0.6964175 1.15697216
##
## $sigma.lv
## LV1 LV2
## 1.803184 1.829261
##
## $Intercept
## Alopacce Alopcune Alopfabr Arctlute Arctperi Auloalbi Pardlugu
## 0.7740314 0.5514740 -0.1420797 -3.5928229 -3.3659708 -0.7311961 0.3187360
## Pardmont Pardnigr Pardpull Trocterr Zoraspin
## 1.6247722 -0.2756281 -0.1351318 2.6556745 0.2459006
##
## $inv.phi
## Alopacce Alopcune Alopfabr Arctlute Arctperi Auloalbi Pardlugu
## 1.3061947 1.4686611 0.7051406 0.8975825 2.3318810 1.5391790 1.1528620
## Pardmont Pardnigr Pardpull Trocterr Zoraspin
## 1.6179020 2.5410961 2.1962333 12.9778575 2.5728355
##
## $phi
## Alopacce Alopcune Alopfabr Arctlute Arctperi Auloalbi Pardlugu
## 0.76558265 0.68089229 1.41815690 1.11410368 0.42883835 0.64969701 0.86740652
## Pardmont Pardnigr Pardpull Trocterr Zoraspin
## 0.61808440 0.39353097 0.45532503 0.07705432 0.38867623
# Where are the predicted latent variable values? just fitp$lvs or
getLV(fitnb)
## LV1 LV2
## Row1 0.92853075 1.270520462
## Row2 -0.68266667 0.793823124
## Row3 0.67620657 1.274453162
## Row4 -0.24715198 1.149862800
## Row5 -0.36104687 1.217244989
## Row6 -0.35232391 1.008699221
## Row7 0.02923422 1.426066555
## Row8 -1.52132529 -0.070690993
## Row9 0.91074271 0.001242368
## Row10 1.03735298 -0.493621331
## Row11 1.48873047 0.303008662
## Row12 1.32414183 0.807369566
## Row13 0.11540128 1.356638522
## Row14 -0.43682288 1.014596948
## Row15 -1.31924354 -0.544650542
## Row16 -1.17468070 -0.242680329
## Row17 -1.11253377 -0.512776547
## Row18 -1.15894159 -0.542933512
## Row19 -1.34067728 -0.502762807
## Row20 -1.36735548 -0.592068352
## Row21 -1.13970043 -0.475608886
## Row22 0.76439162 -1.345945435
## Row23 0.92078501 -1.380620441
## Row24 0.97903815 -1.395240237
## Row25 0.63127901 0.576847735
## Row26 0.27406456 -1.964098487
## Row27 1.11557378 -1.309369913
## Row28 1.01881805 -0.825794766
# Standard errors for parameters:
fitnb$sd
## $theta
## LV1 LV2
## Alopacce 0.0000000 0.0000000
## Alopcune 0.2736250 0.0000000
## Alopfabr 0.3301688 0.2043803
## Arctlute 0.6749237 0.7849125
## Arctperi 0.4757321 0.5592202
## Auloalbi 0.4407849 0.3892596
## Pardlugu 0.2275827 0.2005392
## Pardmont 0.2196722 0.1816350
## Pardnigr 0.4734810 0.3799187
## Pardpull 0.4966106 0.4106393
## Trocterr 0.2098656 0.1568704
## Zoraspin 0.3480311 0.2796547
##
## $sigma.lv
## LV1 LV2
## 0.4163238 0.4257728
##
## $beta0
## Alopacce Alopcune Alopfabr Arctlute Arctperi Auloalbi Pardlugu Pardmont
## 0.4518426 0.4630211 0.5478094 1.7105084 1.4645830 0.7893117 0.4391419 0.3996807
## Pardnigr Pardpull Trocterr Zoraspin
## 0.7870466 0.8340609 0.3339015 0.5830968
##
## $inv.phi
## Alopacce Alopcune Alopfabr Arctlute Arctperi Auloalbi Pardlugu Pardmont
## 0.6025074 0.6026066 0.3957455 0.5787026 1.8042574 0.8383737 0.5810483 0.7756907
## Pardnigr Pardpull Trocterr Zoraspin
## 1.3150328 1.2472485 6.8923434 1.2850971
##
## $phi
## Alopacce Alopcune Alopfabr Arctlute Arctperi Auloalbi Pardlugu
## 0.35313973 0.27937704 0.79591117 0.71830131 0.33180715 0.35388276 0.43717731
## Pardmont Pardnigr Pardpull Trocterr Zoraspin
## 0.29633583 0.20365469 0.25858067 0.04092238 0.19413861
E4. Fit model with different numbers of latent variables.
4. Default number of latent variables is 2. Let’s try 1 and 3 latent variables as well:
# In exercise 2, we fitted GLLVM with two latent variables
fitnb
## Call:
## gllvm(y = spider$abund, family = "negative.binomial", num.lv = 2)
## family:
## [1] "negative.binomial"
## method:
## [1] "VA"
##
## log-likelihood: -733.6806
## Residual degrees of freedom: 289
## AIC: 1561.361
## AICc: 1577.028
## BIC: 1740.765
# How about 1 or 3 LVs
fitnb1 <- gllvm(y=spider$abund, family = "negative.binomial", num.lv = 1)
fitnb1
## Call:
## gllvm(y = spider$abund, family = "negative.binomial", num.lv = 1)
## family:
## [1] "negative.binomial"
## method:
## [1] "VA"
##
## log-likelihood: -759.4012
## Residual degrees of freedom: 300
## AIC: 1590.802
## AICc: 1599.712
## BIC: 1728.218
getLV(fitnb1)
## LV1
## Row1 -0.81681625
## Row2 -0.94961497
## Row3 -0.91688412
## Row4 -1.10570538
## Row5 -1.22149566
## Row6 -1.03403695
## Row7 -1.26771848
## Row8 -0.53475085
## Row9 0.36605635
## Row10 1.00893127
## Row11 0.31290711
## Row12 -0.31672312
## Row13 -1.17622503
## Row14 -1.03499902
## Row15 -0.09009148
## Row16 -0.27458427
## Row17 -0.02446541
## Row18 -0.02079998
## Row19 -0.12969206
## Row20 -0.06888930
## Row21 -0.04323509
## Row22 1.54084844
## Row23 1.65026896
## Row24 1.68381964
## Row25 -0.28901141
## Row26 1.92920394
## Row27 1.62341238
## Row28 1.20021093
fitnb3 <- gllvm(y=spider$abund, family = "negative.binomial", num.lv = 3)
fitnb3
## Call:
## gllvm(y = spider$abund, family = "negative.binomial", num.lv = 3)
## family:
## [1] "negative.binomial"
## method:
## [1] "VA"
##
## log-likelihood: -733.6806
## Residual degrees of freedom: 279
## AIC: 1581.361
## AICc: 1605.145
## BIC: 1798.937
getLV(fitnb3)
## LV1 LV2 LV3
## Row1 0.9285280 1.270523296 -1.906262e-08
## Row2 -0.6826760 0.793817104 -6.482447e-07
## Row3 0.6762101 1.274457765 -2.637684e-07
## Row4 -0.2471556 1.149862274 -4.146394e-07
## Row5 -0.3610549 1.217242067 -7.737033e-07
## Row6 -0.3523178 1.008700338 7.419417e-08
## Row7 0.0292200 1.426062246 2.553078e-07
## Row8 -1.5213439 -0.070707083 1.237777e-06
## Row9 0.9107413 0.001236586 8.756990e-07
## Row10 1.0373539 -0.493608240 1.201402e-06
## Row11 1.4887138 0.303009114 9.264802e-07
## Row12 1.3241484 0.807375857 1.225592e-06
## Row13 0.1153850 1.356635351 -2.180724e-07
## Row14 -0.4368170 1.014598708 4.452870e-07
## Row15 -1.3192485 -0.544658800 -2.776771e-07
## Row16 -1.1746781 -0.242686332 -2.502169e-07
## Row17 -1.1125335 -0.512785345 -3.091623e-07
## Row18 -1.1589465 -0.542944936 -6.100748e-08
## Row19 -1.3406718 -0.502768504 -1.453766e-07
## Row20 -1.3673522 -0.592075794 8.103059e-08
## Row21 -1.1397073 -0.475619582 5.158634e-07
## Row22 0.7643968 -1.345953229 -3.429457e-07
## Row23 0.9207897 -1.380624691 -3.375685e-08
## Row24 0.9790484 -1.395239169 1.037121e-08
## Row25 0.6312727 0.576844206 -2.075276e-06
## Row26 0.2740843 -1.964105990 -6.658805e-07
## Row27 1.1155616 -1.309372960 2.736784e-09
## Row28 1.0188120 -0.825794923 -1.942326e-07
E5. Include environmental variables to the GLLVM and explore the model fit.
5. Environmental variables can be included
with an argument X
:
fitnbx <- gllvm(y = spider$abund, X = spider$x, family = "negative.binomial", seed = 123, num.lv = 2)
fitnbx
## Call:
## gllvm(y = spider$abund, X = spider$x, family = "negative.binomial",
## num.lv = 2, seed = 123)
## family:
## [1] "negative.binomial"
## method:
## [1] "VA"
##
## log-likelihood: -588.9187
## Residual degrees of freedom: 217
## AIC: 1415.837
## AICc: 1548.06
## BIC: 1870.074
coef(fitnbx)
## $Species.scores
## LV1 LV2
## Alopacce 1.000000e+00 0.00000000
## Alopcune 2.201376e+00 1.00000000
## Alopfabr 1.600175e+00 -0.02790578
## Arctlute 2.864153e+00 0.85491601
## Arctperi -2.611968e-07 -2.41258495
## Auloalbi 1.491118e+00 3.19928366
## Pardlugu 3.944288e-01 -0.02065962
## Pardmont 8.907405e-01 0.15136216
## Pardnigr 2.417516e+00 -3.48347325
## Pardpull 1.680954e+00 2.24819374
## Trocterr 1.030635e+00 -0.67087884
## Zoraspin 1.570957e+00 -2.45793904
##
## $sigma.lv
## LV1 LV2
## 4.769211e-01 1.750845e-08
##
## $Intercept
## Alopacce Alopcune Alopfabr Arctlute Arctperi Auloalbi
## -1.8064046 -4.6628013 -4.2140438 -15.5681238 -14.9088011 -16.3558605
## Pardlugu Pardmont Pardnigr Pardpull Trocterr Zoraspin
## 7.9303148 -6.3995949 -5.6547891 -13.6114971 -0.3336265 -4.1372776
##
## $Xcoef
## soil.dry bare.sand fallen.leaves moss herb.layer
## Alopacce -0.8878738 -0.009315833 -0.291126554 0.274014193 0.65118653
## Alopcune 1.3901366 -0.516772190 0.007261267 -0.136642394 0.48662594
## Alopfabr -0.7974089 0.823100137 -0.145041818 0.531349894 0.42565781
## Arctlute 6.2604058 -0.006996697 -1.824637605 0.502257514 -0.09695928
## Arctperi -1.7801727 0.238572359 -2.157239869 0.495821007 0.02126666
## Auloalbi 0.3204160 -0.134778257 0.608841892 0.129651631 4.18697844
## Pardlugu -2.5394813 -0.732449351 0.364909249 -0.358249299 0.60351399
## Pardmont 1.6381786 0.137509982 -0.546863657 0.917166651 0.70949096
## Pardnigr 2.6361823 -0.161228714 -0.857110295 -0.350929172 0.84806179
## Pardpull 3.0903528 -0.454461209 -0.478489258 0.447283079 2.07099025
## Trocterr 1.2578039 -0.263436888 -0.228903368 -0.158047787 0.47711404
## Zoraspin 2.1516927 0.046123722 -0.577840336 -0.005416612 0.67469059
## reflection
## Alopacce 0.69602739
## Alopcune 0.31252195
## Alopfabr 0.52347182
## Arctlute -0.85619380
## Arctperi 4.00643750
## Auloalbi -0.66909955
## Pardlugu -1.19124727
## Pardmont 0.04132679
## Pardnigr -0.68171846
## Pardpull -0.48741030
## Trocterr -0.33629434
## Zoraspin -1.00338851
##
## $inv.phi
## Alopacce Alopcune Alopfabr Arctlute Arctperi Auloalbi
## 2.063410e+01 3.532395e+00 9.535779e+00 2.266454e+00 4.640004e+07 1.096939e+01
## Pardlugu Pardmont Pardnigr Pardpull Trocterr Zoraspin
## 3.466149e+01 2.199583e+00 9.423731e+00 1.904354e+01 2.691070e+01 6.434174e+00
##
## $phi
## Alopacce Alopcune Alopfabr Arctlute Arctperi Auloalbi
## 4.846347e-02 2.830941e-01 1.048682e-01 4.412180e-01 2.155171e-08 9.116278e-02
## Pardlugu Pardmont Pardnigr Pardpull Trocterr Zoraspin
## 2.885047e-02 4.546317e-01 1.061151e-01 5.251125e-02 3.715994e-02 1.554201e-01
# confidence intervals for parameters:
confint(fitnbx)
## 2.5 % 97.5 %
## theta.LV1.1 3.412564e-01 6.125858e-01
## theta.LV1.2 -2.252097e-05 2.255599e-05
## theta.LV1.3 1.000000e+00 1.000000e+00
## theta.LV1.4 2.197535e+00 2.205217e+00
## theta.LV1.5 1.594203e+00 1.606147e+00
## theta.LV1.6 2.861504e+00 2.866801e+00
## theta.LV1.7 -8.936370e-04 8.931146e-04
## theta.LV1.8 1.485669e+00 1.496567e+00
## theta.LV1.9 3.907375e-01 3.981202e-01
## theta.LV1.10 8.840093e-01 8.974717e-01
## theta.LV1.11 2.400409e+00 2.434624e+00
## theta.LV1.12 1.641161e+00 1.720746e+00
## theta.LV2.1 9.720619e-01 1.089209e+00
## theta.LV2.2 1.563848e+00 1.578067e+00
## theta.LV2.3 0.000000e+00 0.000000e+00
## theta.LV2.4 1.000000e+00 1.000000e+00
## theta.LV2.5 -2.790578e-02 -2.790578e-02
## theta.LV2.6 8.549160e-01 8.549160e-01
## theta.LV2.7 -2.412585e+00 -2.412585e+00
## theta.LV2.8 3.199284e+00 3.199284e+00
## theta.LV2.9 -2.065962e-02 -2.065962e-02
## theta.LV2.10 1.513622e-01 1.513622e-01
## theta.LV2.11 -3.483473e+00 -3.483473e+00
## theta.LV2.12 2.248194e+00 2.248194e+00
## sigma.LV1 -6.708788e-01 -6.708788e-01
## sigma.LV2 -2.457939e+00 -2.457939e+00
## Intercept.Alopacce -1.812280e+00 -1.800529e+00
## Intercept.Alopcune -4.674639e+00 -4.650964e+00
## Intercept.Alopfabr -4.224739e+00 -4.203349e+00
## Intercept.Arctlute -1.558161e+01 -1.555464e+01
## Intercept.Arctperi -1.491537e+01 -1.490223e+01
## Intercept.Auloalbi -1.636441e+01 -1.634732e+01
## Intercept.Pardlugu 7.922342e+00 7.938288e+00
## Intercept.Pardmont -6.409584e+00 -6.389605e+00
## Intercept.Pardnigr -5.664810e+00 -5.644768e+00
## Intercept.Pardpull -1.361989e+01 -1.360310e+01
## Intercept.Trocterr -3.410847e-01 -3.261682e-01
## Intercept.Zoraspin -4.147216e+00 -4.127339e+00
## Xcoef.soil.dry:Alopacce -9.237258e-01 -8.520218e-01
## Xcoef.soil.dry:Alopcune 1.349472e+00 1.430801e+00
## Xcoef.soil.dry:Alopfabr -8.197262e-01 -7.750915e-01
## Xcoef.soil.dry:Arctlute 6.218875e+00 6.301936e+00
## Xcoef.soil.dry:Arctperi -1.787646e+00 -1.772700e+00
## Xcoef.soil.dry:Auloalbi 2.865838e-01 3.542481e-01
## Xcoef.soil.dry:Pardlugu -2.558985e+00 -2.519978e+00
## Xcoef.soil.dry:Pardmont 1.570186e+00 1.706171e+00
## Xcoef.soil.dry:Pardnigr 2.595635e+00 2.676729e+00
## Xcoef.soil.dry:Pardpull 3.043656e+00 3.137049e+00
## Xcoef.soil.dry:Trocterr 1.224275e+00 1.291333e+00
## Xcoef.soil.dry:Zoraspin 2.116890e+00 2.186495e+00
## Xcoef.bare.sand:Alopacce -1.074288e-01 8.879716e-02
## Xcoef.bare.sand:Alopcune -5.297806e-01 -5.037638e-01
## Xcoef.bare.sand:Alopfabr 7.961501e-01 8.500502e-01
## Xcoef.bare.sand:Arctlute -1.648518e-02 2.491786e-03
## Xcoef.bare.sand:Arctperi 2.142026e-01 2.629421e-01
## Xcoef.bare.sand:Auloalbi -1.700558e-01 -9.950076e-02
## Xcoef.bare.sand:Pardlugu -7.513930e-01 -7.135057e-01
## Xcoef.bare.sand:Pardmont 6.414102e-02 2.108789e-01
## Xcoef.bare.sand:Pardnigr -2.007248e-01 -1.217326e-01
## Xcoef.bare.sand:Pardpull -5.101206e-01 -3.988018e-01
## Xcoef.bare.sand:Trocterr -3.811233e-01 -1.457505e-01
## Xcoef.bare.sand:Zoraspin 2.892192e-02 6.332553e-02
## Xcoef.fallen.leaves:Alopacce -2.949788e-01 -2.872743e-01
## Xcoef.fallen.leaves:Alopcune -9.378432e-02 1.083068e-01
## Xcoef.fallen.leaves:Alopfabr -1.467799e-01 -1.433038e-01
## Xcoef.fallen.leaves:Arctlute -1.837483e+00 -1.811792e+00
## Xcoef.fallen.leaves:Arctperi -2.157240e+00 -2.157240e+00
## Xcoef.fallen.leaves:Auloalbi 4.899677e-01 7.277161e-01
## Xcoef.fallen.leaves:Pardlugu 2.962014e-01 4.336171e-01
## Xcoef.fallen.leaves:Pardmont -6.051007e-01 -4.886266e-01
## Xcoef.fallen.leaves:Pardnigr -9.480451e-01 -7.661755e-01
## Xcoef.fallen.leaves:Pardpull -5.683111e-01 -3.886675e-01
## Xcoef.fallen.leaves:Trocterr -2.939830e-01 -1.638237e-01
## Xcoef.fallen.leaves:Zoraspin -6.752642e-01 -4.804165e-01
## Xcoef.moss:Alopacce 2.429067e-01 3.051217e-01
## Xcoef.moss:Alopcune -1.658938e-01 -1.073910e-01
## Xcoef.moss:Alopfabr 5.010307e-01 5.616691e-01
## Xcoef.moss:Arctlute 4.825618e-01 5.219532e-01
## Xcoef.moss:Arctperi 4.759735e-01 5.156686e-01
## Xcoef.moss:Auloalbi 1.078977e-01 1.514056e-01
## Xcoef.moss:Pardlugu -3.851409e-01 -3.313577e-01
## Xcoef.moss:Pardmont 8.346161e-01 9.997172e-01
## Xcoef.moss:Pardnigr -3.981595e-01 -3.036989e-01
## Xcoef.moss:Pardpull 3.261368e-01 5.684293e-01
## Xcoef.moss:Trocterr -2.748672e-01 -4.122841e-02
## Xcoef.moss:Zoraspin -2.378061e-02 1.294739e-02
## Xcoef.herb.layer:Alopacce 6.000648e-01 7.023083e-01
## Xcoef.herb.layer:Alopcune 4.402765e-01 5.329754e-01
## Xcoef.herb.layer:Alopfabr 3.818734e-01 4.694422e-01
## Xcoef.herb.layer:Arctlute -1.558862e-01 -3.803234e-02
## Xcoef.herb.layer:Arctperi 5.889576e-03 3.664374e-02
## Xcoef.herb.layer:Auloalbi 4.151275e+00 4.222682e+00
## Xcoef.herb.layer:Pardlugu 5.295818e-01 6.774462e-01
## Xcoef.herb.layer:Pardmont 6.420815e-01 7.769004e-01
## Xcoef.herb.layer:Pardnigr 8.043680e-01 8.917556e-01
## Xcoef.herb.layer:Pardpull 2.017884e+00 2.124096e+00
## Xcoef.herb.layer:Trocterr 4.176353e-01 5.365928e-01
## Xcoef.herb.layer:Zoraspin 6.309830e-01 7.183982e-01
## Xcoef.reflection:Alopacce 6.718149e-01 7.202399e-01
## Xcoef.reflection:Alopcune 2.611065e-01 3.639374e-01
## Xcoef.reflection:Alopfabr 4.880824e-01 5.588612e-01
## Xcoef.reflection:Arctlute -8.874129e-01 -8.249747e-01
## Xcoef.reflection:Arctperi 3.979206e+00 4.033669e+00
## Xcoef.reflection:Auloalbi -7.274869e-01 -6.107122e-01
## Xcoef.reflection:Pardlugu -1.243111e+00 -1.139383e+00
## Xcoef.reflection:Pardmont -1.403512e-02 9.668869e-02
## Xcoef.reflection:Pardnigr -7.292709e-01 -6.341661e-01
## Xcoef.reflection:Pardpull -5.525356e-01 -4.222850e-01
## Xcoef.reflection:Trocterr -4.643246e-01 -2.082641e-01
## Xcoef.reflection:Zoraspin -1.046829e+00 -9.599477e-01
## inv.phi.Alopacce 2.062497e+01 2.064323e+01
## inv.phi.Alopcune 3.519971e+00 3.544819e+00
## inv.phi.Alopfabr 9.528301e+00 9.543258e+00
## inv.phi.Arctlute 2.265933e+00 2.266974e+00
## inv.phi.Arctperi 4.640004e+07 4.640004e+07
## inv.phi.Auloalbi 1.096598e+01 1.097280e+01
## inv.phi.Pardlugu 3.464960e+01 3.467337e+01
## inv.phi.Pardmont 2.192376e+00 2.206789e+00
## inv.phi.Pardnigr 9.408806e+00 9.438655e+00
## inv.phi.Pardpull 1.903077e+01 1.905630e+01
## inv.phi.Trocterr 2.674175e+01 2.707965e+01
## inv.phi.Zoraspin 6.420768e+00 6.447580e+00
I have problems in model fitting. My model
converges to infinity or local maxima: GLLVMs are complex models
where starting values have a big role. Choosing a different starting
value method (see argument starting.val
) or use multiple
runs and pick up the one giving highest log-likelihood value using
argument n.init
. More variation to the starting points can
be added with jitter.var
.
My results does not look the same as in answers: The results may not be exactly the same as in the answers, as the initial values for each model fit are slightly different, so the results may also differ slightly.
GLLVMs can be used as a model-based approach to unconstrained ordination by including two latent variables in the model: \(g(E(y_{ij})) = \beta_{0j} + \boldsymbol{u}_i'\boldsymbol{\theta}_j\)
The latent variable term try to capture the underlying factors driving species abundances at sites.
Predictions for the two latent variables, \(\boldsymbol{\hat u}_i=(\hat u_{i1}, \hat u_{i2})\), then provide coordinates for sites in the ordination plot and then provides a graphical representation of which sites are similar in terms of their species composition.
ordiplot()
produces ordination plots based on fitted
GLLVMs.biplot = TRUE
in
ordiplot()
).# Arbitrary color palette, a vector length of 20. Can use, for example, colorRampPalette from package grDevices
rbPal <- c("#00FA9A", "#00EC9F", "#00DFA4", "#00D2A9", "#00C5AF", "#00B8B4", "#00ABB9", "#009DBF", "#0090C4", "#0083C9", "#0076CF", "#0069D4", "#005CD9", "#004EDF", "#0041E4", "#0034E9", "#0027EF", "#001AF4", "#000DF9", "#0000FF")
X <- spider$x
par(mfrow = c(3,2), mar=c(4,4,2,2))
for(i in 1:ncol(X)){
Col <- rbPal[as.numeric(cut(X[,i], breaks = 20))]
ordiplot(fitnb, symbols = T, s.colors = Col, main = colnames(X)[i],
biplot = TRUE)
}
Here environmental gradients stand out quite clearly, indicating that, at least, some of the differences in species compositions at sites can be explained by the differences in environmental conditions.
The next step would be to include covariates to the model to study more precisely the effects of environmental variables: \(g(E(y_{ij})) = \beta_{0j} + \boldsymbol{x}_i'\boldsymbol{\beta}_{j} + \boldsymbol{u}_i'\boldsymbol{\theta}_j\)
Niku, J., F.K.C. Hui, S. Taskinen, and D.I. Warton. 2019. Gllvm - Fast Analysis of Multivariate Abundance Data with Generalized Linear Latent Variable Models in R. 10. Methods in Ecology and Evolution: 2173–82↩︎
Kasper Kristensen, Anders Nielsen, Casper W. Berg, Hans Skaug, Bradley M. Bell (2016). TMB: Automatic Differentiation and Laplace Approximation. Journal of Statistical Software, 70(5), 1-21↩︎
Hui, F. K. C., Warton, D., Ormerod, J., Haapaniemi, V., and Taskinen, S. (2017). Variational approximations for generalized linear latent variable models. Journal of Computational and Graphical Statistics. Journal of Computational and Graphical Statistics, 26:35-43↩︎
Korhonen, P., Hui, F. K. C., Niku, J., and Taskinen, S. (2021). Fast, universal estimation of latent variable models using extended variational approximations, arXiv:2107.02627 .↩︎
Niku, J., Warton, D. I., Hui, F. K. C., and Taskinen, S. (2017). Generalized linear latent variable models for multivariate count and biomass data in ecology. Journal of Agricultural, Biological, and Environmental Statistics, 22:498-522.↩︎
van der Aart, P. J. M., and Smeenk-Enserink, N. (1975) Correlations between distributions of hunting spiders (Lycosidae, Ctenidae) and environmental characteristics in a dune area. Netherlands Journal of Zoology 25, 1-45.↩︎
Dunn, P. K., and Smyth, G. K. (1996). Randomized quantile residuals. Journal of Computational and Graphical Statistics, 5, 236-244.↩︎
Gabriel, K. R. (1971). The biplot graphic display of matrices with application to principal component analysis. Biometrika, 58, 453-467↩︎