library(tibble)
library(dplyr)
library(ggplot2)
Aquest és un cas molt conegut, tractat de manera molt completa per Wood i reprès i adaptat per García Perez. És interessant per la gran complexitat d’elemnts que hi entren en joc i per la possibilitat d’analitzar-la des de diferents aproximacions.
L’estimació del nombre de peixos dels bancs de pesca és de gran importància avui dia atès que alguns estan gairebé esgotats i diversos organismes fixen les quotes de captura depenent d’aquestes estimacions.
La dificultat fonamental en l’estimació de tal nombre rau en la impossibilitat de la obtenció de dades, és a dir, de peixos vius. Per aquesta raó el recompte d’ous de les espècies és el mètode habitual d’estimació del nombre d’adults (o més sovint massa d’adults) ja que la taxa de producció d’ous per quilogram d’adult és fàcil d’obtenir a partir dels peixos capturats a les xarxes d’arrossegament.
Més concretament, s’estableix una cadena d’estacions de mostreig a l’àrea de recerca i s’anota el nombre d’ous de l’espècie en estudi que apareixen en unes malles extretes del fons del mar, coneixent-ne el volum d’aigua mostrejada. S’anota així el nombre d’ous de l’espècie a l’estudi per metre cúbic d’aigua.
Les dades mack de la llibreria gamair
corresponen a un estudi d’aquestes característiques sobre ous de verat
(Scomber scombrus) dut a terme per Borchers et al. (1997). En
aquestes dades apareixen, entre d’altres, les variables
egg.count, nombre d’ous en estat I al mostreig realitzat
(és a dir, a la malla extreta); b.depth, profunditat del
llit marí a la qual es va fer el mostreig; c.dist,
distància des del lloc de mostreig al contorn de llit marí de 200
metres, distància mesurada en graus; lon, longitud de
l’estació de mostreig en graus est; lat, latitud de
l’estació de mostreig a graus nord; salinity, salinitat de l’aigua a
l’estació de mostreig; temp.surf, temperatura de la
superfície de l’aigua a l’estació de mostreig; temp.20m,
temperatura de l’aigua a 20 metres de profunditat a l’estació de
mostreig.
library(gamair)
data("mack")
str(mack)
## 'data.frame': 634 obs. of 16 variables:
## $ egg.count : num 0 0 0 1 4 3 0 1 0 0 ...
## $ egg.dens : num 0 0 0 18.3 90.2 ...
## $ b.depth : num 4342 4334 4286 1438 166 ...
## $ lat : num 44.6 44.6 44.6 44 44 ...
## $ lon : num -4.65 -4.48 -4.3 -2.87 -2.07 -2.13 -2.27 -2.35 -2.42 -2.48 ...
## $ time : num 8.23 9.68 10.9 19.33 8.78 ...
## $ salinity : num 35.7 35.7 35.7 35.7 NA ...
## $ flow : num 417 405 377 420 354 373 375 364 375 362 ...
## $ s.depth : num 104 98 101 98 101 100 100 102 100 100 ...
## $ temp.surf : num 15 15.4 15.9 16.6 16.7 16.6 17.1 17.1 17.3 16.9 ...
## $ temp.20m : num 15 15.4 15.9 16.6 16.7 16.6 17.1 17.1 17.3 16.9 ...
## $ net.area : num 0.242 0.242 0.242 0.242 0.242 0.242 0.242 0.242 0.242 0.242 ...
## $ country : Factor w/ 4 levels "EN","fr","IR",..: 4 4 4 4 4 4 4 4 4 4 ...
## $ vessel : Factor w/ 4 levels "CIRO","COSA",..: 2 2 2 2 2 2 2 2 2 2 ...
## $ vessel.haul: num 22 23 24 93 178 179 181 182 183 184 ...
## $ c.dist : num 0.84 0.859 0.893 0.396 0.04 ...
El propòsit és determinar un model que expliqui prou bé a la variable
dependent egg.count en funció de les altres covariables
independents.
En primer lloc podem geolocalitzar les densitats,
egg.dens (una altra de les variables subministrades amb les
dades encara que no considerada al model a ajustar) aprofitant les
variables lon i lat . Això, ens donarà una
idea de la grandària de l’àrea de mostreig: important per entendre les
diferències que existeixen entre variables.
Per fer això geo localitzarem els punts de mostreig en un mapa d’ESRI creant una capa de visualització de densitat dels ous als diferents punts de mostreig.
library(sf)
library(tmap)
mack_sf <- st_as_sf(mack[,c(5,4,2,1,3,16,7,10,11,12)],
coords = c("lon", "lat"), crs = 4326)
tmap_mode("view")
tm_shape(mack_sf) +
tm_dots(size = 'egg.dens',
fill = "yellow2", fill_alpha = .5,
popup.vars=c("Densitat ous en fase I (ous/m2): "= "egg.dens",
"Nombre d'ous en fase I: "= "egg.count",
"Profunditat del fons marí: "= "b.depth",
"Distància de la isòbata de 200m en graus: "= "c.dist",
"Salinitat de l'aigua: "= "salinity",
"Temperatura de l'aigua en superfície: "= "temp.surf",
"Temperatura de l'aigua a 20m de profund.: "= "temp.20m",
"Àrea de mostreig en m2: "= "net.area"))+
tmap_options(basemaps = "Esri.WorldImagery")
Començarem l’anàlisi amb una aproximació gradual, mirant primer com funcionen els models lineals generalitzats amb aquestes dades.
Com que egg.count, el recompte d’ous, és la variable de
resposta, com a primer pas sembla raonable ajustar un model GLM de
Poisson.
fit.glm <- glm(formula = egg.count~ lon+lat+b.depth+c.dist+salinity+temp.surf+temp.20m,
data = mack,
family = poisson)
summary(fit.glm)
##
## Call:
## glm(formula = egg.count ~ lon + lat + b.depth + c.dist + salinity +
## temp.surf + temp.20m, family = poisson, data = mack)
##
## Coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -3.319e+01 6.021e+00 -5.513 3.53e-08 ***
## lon -2.919e-01 1.257e-02 -23.224 < 2e-16 ***
## lat -8.325e-02 1.985e-02 -4.194 2.74e-05 ***
## b.depth 1.365e-04 2.011e-05 6.787 1.14e-11 ***
## c.dist -5.233e-01 3.890e-02 -13.454 < 2e-16 ***
## salinity 1.198e+00 1.606e-01 7.460 8.65e-14 ***
## temp.surf -9.571e-02 3.614e-02 -2.648 0.00809 **
## temp.20m -2.536e-01 3.001e-02 -8.451 < 2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for poisson family taken to be 1)
##
## Null deviance: 9656.4 on 329 degrees of freedom
## Residual deviance: 3737.4 on 322 degrees of freedom
## (304 observations deleted due to missingness)
## AIC: 4679.4
##
## Number of Fisher Scoring iterations: 6
Aparentment, l’ajustament és correcte, amb unes les variables explicatives seleccionades que tenen efecte significatiu sobre la resposta.
Avaluarem ara la distribució dels valors residuals,
par(mfrow=c(2,2))
plot(fit.glm)
Cal afegir que el quocient Residual deviance /
Degrees of freedom és 11.58, molt alt,
indicant una problemàtica de sobredispersió.
fit.glm.q <- glm(egg.count~ lon+lat+b.depth+c.dist+salinity+temp.surf+temp.20m,
data = mack, family = quasipoisson())
summary(fit.glm.q)
##
## Call:
## glm(formula = egg.count ~ lon + lat + b.depth + c.dist + salinity +
## temp.surf + temp.20m, family = quasipoisson(), data = mack)
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -3.319e+01 2.445e+01 -1.358 0.17547
## lon -2.919e-01 5.103e-02 -5.720 2.43e-08 ***
## lat -8.325e-02 8.059e-02 -1.033 0.30234
## b.depth 1.365e-04 8.164e-05 1.672 0.09553 .
## c.dist -5.233e-01 1.579e-01 -3.314 0.00103 **
## salinity 1.198e+00 6.519e-01 1.837 0.06707 .
## temp.surf -9.571e-02 1.467e-01 -0.652 0.51469
## temp.20m -2.536e-01 1.218e-01 -2.082 0.03816 *
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for quasipoisson family taken to be 16.48351)
##
## Null deviance: 9656.4 on 329 degrees of freedom
## Residual deviance: 3737.4 on 322 degrees of freedom
## (304 observations deleted due to missingness)
## AIC: NA
##
## Number of Fisher Scoring iterations: 6
Aquest model no sembra presentar resultats acceptables, amb tan sols
3 variables significatives i sense resoldre les problemàtiques de sobre
dispersió (Residual deviance /
Degrees of freedom = 3717/321)
fit.bn <- MASS::glm.nb(egg.count~ lon+lat+b.depth+c.dist+salinity+temp.surf+temp.20m,
data = mack)
summary(fit.bn)
##
## Call:
## MASS::glm.nb(formula = egg.count ~ lon + lat + b.depth + c.dist +
## salinity + temp.surf + temp.20m, data = mack, init.theta = 0.8161460249,
## link = log)
##
## Coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -1.289e+01 1.775e+01 -0.727 0.4675
## lon -3.178e-01 6.487e-02 -4.898 9.66e-07 ***
## lat -7.266e-02 1.113e-01 -0.653 0.5140
## b.depth 1.335e-04 9.277e-05 1.439 0.1503
## c.dist -9.002e-01 1.916e-01 -4.697 2.64e-06 ***
## salinity 6.593e-01 4.495e-01 1.467 0.1425
## temp.surf -2.257e-01 1.455e-01 -1.551 0.1209
## temp.20m -2.435e-01 1.023e-01 -2.380 0.0173 *
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for Negative Binomial(0.8161) family taken to be 1)
##
## Null deviance: 841.85 on 329 degrees of freedom
## Residual deviance: 352.87 on 322 degrees of freedom
## (304 observations deleted due to missingness)
## AIC: 1934.7
##
## Number of Fisher Scoring iterations: 1
##
##
## Theta: 0.8161
## Std. Err.: 0.0859
##
## 2 x log-likelihood: -1916.6930
par(mfrow= c(2,2))
plot(fit.bn)
En aquest cas, sí sembla que s’han corregit les problemàtiques de
sobredispersió, amb un quocient
Residual deviance/Degrees of freedom=
1.084, però seguim tenint tan sols 3 variables
significatives.
family=poisson completHem de provar doncs amb un model més general que els GLM: un
model GAM. Com que les variables longitud i
latitud poden anar juntes a l’ajustament, atès que són
covariables de localització, el primer ajustament l’executem a baix, on
hem afegit l’argument scale=-1 per indicar a
l’algoritme que el paràmetre d’escala de la Poisson és
desconegut, i l’argument gamma=1.4 per fixar
problema del sobreajustament.
fit.gam1 <- mgcv::gam(egg.count~s(lon,lat,bs="ts",k=100)+ s(b.depth,bs="ts")+
s(c.dist,bs="ts")+s(salinity,bs="ts")+ s(temp.surf,bs="ts")+
s(temp.20m,bs="ts"),
data=mack,
family=poisson,
scale=-1,
gamma=1.4)
Imprimint el model GAM que acabem d’ajustar veiem que
mgcv ens dona uns valors de graus de llibertat:
fit.gam1
##
## Family: poisson
## Link function: log
##
## Formula:
## egg.count ~ s(lon, lat, bs = "ts", k = 100) + s(b.depth, bs = "ts") +
## s(c.dist, bs = "ts") + s(salinity, bs = "ts") + s(temp.surf,
## bs = "ts") + s(temp.20m, bs = "ts")
##
## Estimated degrees of freedom:
## 62.46 1.86 0.00 1.06 0.00 6.19 total = 72.57
##
## GCV score: 7.374066
Aquest valor són importants per poder valorar la participació de les diferents variables al model
En un Model Additiu Generalitzat (GAM), els graus de
llibertat efectius (\(edf\),
és així com es diuen exactament) d’una variable determinen la
flexibilitat de la funció de suavitzat (spline). No hi ha
un únic valor “correcte”, sinó que els graus de llibertat se seleccionen
automàticament o es limiten mitjançant un paràmetre de penalització
segons la complexitat del patró real en les dades.
En teoria, un cop ajustat el model, el valor de \(edf\) final d’una variable indica la forma de la relació:
| Valor de \(edf\) | Tipus de relació | Significat Visual |
|---|---|---|
| \(edf = 1\) | Lineal | Una línia recta (equivalent a una regressió lineal clàssica) |
| \(1 < edf \leq 2\) | Curvatura simple | Una corba suau amb una sola inflexió (ex. quadràtica o parabòlica) |
| \(edf > 2)\) | No lineal complexa | Corbes amb múltiples pics, valls o patrons ondulats |
| \(edf\) proper a \(k-1\) | Restringit / Saturat | El model volia més flexibilitat però es va quedar sense espai
(k és molt baix). |
A la llum dels graus de llibertat estimats (\(edf\)) que proporciona la sortida, el model
ha pres decisions molt clares i dràstiques sobre cada variable. S’empra
bs = "ts" (thin plate regression
splines with shrinkage) perquè aquest mètode pot reduir
l’edf a exactament 0, eliminant completament les variables que
no aporten al model.
fit.gam1 a la llum dels \(edf\)(lon, lat, bs = “ts”, k = 100) → edf = 62.46
mgcv::gam.check(). Si el valor p per a aquest terme és
superior a 0,05, el k = 100 actual és perfecte. Si és menor a 0.05, és
possible que necessiteu pujar k a 120 o 150. En aquest cas el valor p és
1.00. És a dir, k és perfects(b.depth, bs = “ts”) → edf = 1.86
s(c.dist, bs = “ts”) → edf = 0.00
s(salinity, bs = “ts”) → edf = 1.06
s(temp.surf, bs = “ts”) → edf = 0.00
s(temp.20m, bs = “ts”) → edf = 6.19
family=poisson amb reducció de variables a
ran d’anàlisi de l’\(\small edf\)fit.gam2 <- mgcv::gam(egg.count~s(lon,lat,bs="ts",k=100)+
s(b.depth,bs="ts")+
salinity+
s(temp.20m,bs="ts"),
data=mack,
family=poisson,
scale=-1,
gamma=1.4)
summary(fit.gam2)
##
## Family: poisson
## Link function: log
##
## Formula:
## egg.count ~ s(lon, lat, bs = "ts", k = 100) + s(b.depth, bs = "ts") +
## salinity + s(temp.20m, bs = "ts")
##
## Parametric coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 66.7402 23.4615 2.845 0.00480 **
## salinity -1.8468 0.6628 -2.786 0.00573 **
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Approximate significance of smooth terms:
## edf Ref.df F p-value
## s(lon,lat) 62.462 99 3.745 < 2e-16 ***
## s(b.depth) 1.854 9 0.412 0.065007 .
## s(temp.20m) 6.210 9 2.467 0.000201 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## R-sq.(adj) = 0.807 Deviance explained = 87.9%
## GCV = 7.3681 Scale est. = 5.023 n = 330
El summary ara ens dona dues taules: una de coeficients
paramètric de la qual deduïm que existeix una relació negativa
entre recompes d’ous i salinitat: el recompte d’ous disminueix
a mesura creix la salinitat.
Cal destacar que tant l’ordenada a l’origen com la variable
salinity són significatives.
La taula de termes suavitzats ens indica que tant el paràmetre de
localització (lat,lon) com el de temperatura a 20 m de
profunditat són significatius per a explicar el recompte d’ous, mentre
que veiem que b.depth no arriba a tenir un valor p
significatiu. A més a més, tenint en compte quela profunditat
del fons (b.depth) sol estar fortament lligada a la posició geogràfica,
és molt probable que el terme espacial s(lon, lat) (que té
un \(edf\) enorme de ~62) ja estigui
capturant de forma implícita l’estructura de la profunditat de la costa,
fent que la variable individual b.depth es torni
redundant.
La idea és comparar posteriorment els dos models directament mitjanant el Criteri d’Informació d’Akaike (AIC)
family=poisson sense la variable
b.depthAjustem per tant el model sense b.depth
fit.gam3 <- mgcv::gam(egg.count~s(lon,lat,bs="ts",k=100)+
# s(b.depth,bs="ts")+
salinity+
s(temp.20m,bs="ts"),
data=mack,
family=poisson,
scale=-1,
gamma=1.4)
summary(fit.gam3)
##
## Family: poisson
## Link function: log
##
## Formula:
## egg.count ~ s(lon, lat, bs = "ts", k = 100) + salinity + s(temp.20m,
## bs = "ts")
##
## Parametric coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 67.6694 23.4989 2.880 0.00431 **
## salinity -1.8732 0.6639 -2.822 0.00515 **
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Approximate significance of smooth terms:
## edf Ref.df F p-value
## s(lon,lat) 63.495 99 4.535 < 2e-16 ***
## s(temp.20m) 6.572 9 2.665 0.000129 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## R-sq.(adj) = 0.805 Deviance explained = 87.9%
## GCV = 7.3428 Scale est. = 5.0464 n = 330
Veiem, com era previsible que tots els termes implicats en el
model fit.gam3 són significatius. A més a més,
comparant l’AIC d’ambdós models,
AIC(fit.gam2, fit.gam3) %>%
mutate(diff= AIC-lead(AIC))
## df AIC diff
## fit.gam2 73.52511 2236.466 -1.617587
## fit.gam3 73.06699 2238.083 NA
veiem que la diferència d’AIC, perden la variable profunditat és mínima (1.617). Amb la qual cosa podem condsidera perfectament raonable apartarla del model
La variable profunditat de fons es retira doncs del model final pel fet que no assoleix el nivell de significació estadística estàndard (\(\alpha = 0.05, p = 0.065\)) i la seva exclusió resulta en un model més parsimoniós (amb menor o equivalent AIC).
par(mfrow=c(2,2))
mgcv::gam.check(fit.gam3)
##
## Method: GCV Optimizer: outer newton
## full convergence after 7 iterations.
## Gradient range [1.010947e-11,1.237273e-09]
## (score 7.342831 & scale 5.046431).
## Hessian positive definite, eigenvalue range [0.0348293,0.410599].
## Model rank = 110 / 110
##
## Basis dimension (k) checking results. Low p-value (k-index<1) may
## indicate that k is too low, especially if edf is close to k'.
##
## k' edf k-index p-value
## s(lon,lat) 99.00 63.50 1.10 1.00
## s(temp.20m) 9.00 6.57 0.92 0.23
Tot i les millores que hem anat introduint al model, aquest segueix presentant una distribució de residuals insatisfactòria, sobretot en el gràfic de valors residuals per quantils teòrics (Q-Q plot). Si els punts del gràfic Q-Q formen una corba en forma de “S” o es disparen fortament cap amunt a l’extrem dret, hi ha un problema de sobredispersió (la variabilitat de les dades és molt més gran del que s’esperava) o un excés de zeros (moltes estacions de mostreig sense ous).
Per tant, hem de descartar també aquest model.
L’ús de family = poisson amb una variable resposta de
tipus recompte d’ous (egg.count) en
ecologia marina és la causa directa de la sobredispersió
extrema. Els ous de peixos (com el sorell o el verat del
dataset mack) es distribueixen en agregacions massives
a l’oceà (cardums de fresa), la qual cosa genera una quantitat
enorme de zeros (llances sense ous) combinada amb
llances amb desenes de milers d’ous. La
distribució de Poisson assumeix que la variància és
igual a la mitjana (Var(Y) = μ), cosa que mai
ocorre en aquestes dades de fresa, on la variància és
exponencialment més gran.
En la funció gam(), per a aquesta situació que es
plantejar és un canvi de família de distribució d’errors. Les
alternatives serien (disposades en ordre decreixent d’eficàcia): -
Família Tweedie (family = tw()): És actualment
l’estàndard d’or en ecologia pesquera. Gestiona de
forma excel·lent una combinació de molts zeros continus i valors
extremadament alts. - Binomial Negativa (family =
nb()): Ideal si les teves dades són estrictament nombres enters
(0, 1, 2…) i hi ha molta variància. És molt superior a la
distribució poisson. - Famílies per a excés de zeros
(family = ziap)**: Si el teu gràfic Q-Q falla principalment perquè tens
una enorme quantitat de zeros reals (zones on mai hi ha fresa).
En ecologia pesquera, les dades de Captura per Unitat d’Esforç (CPUE) o biomassa combinen dues naturaleses:
La família Tweedie (específicament quan el paràmetre de potència \(1 < p < 2\) es defineix formalment com un procés compost de Poisson-Gamma:
family = tw(), mgcv estimarà automàticament
per màxima versemblança un paràmetre de potència entre 1 i 2. Això
modelarà les teves dades com un procés on la variància escala amb la
mitjana de forma flexible.gamma.family=tw()library(mgcv)
fit.gam.tw2 <- mgcv::gam(egg.count ~s(lon,lat,bs="ts",k=100)+
s(b.depth,bs="ts")+
s(c.dist,bs="ts")+
s(salinity,bs="ts")+
s(temp.surf,bs="ts")+
s(temp.20m,bs="ts"),
data = mack,
family = tw(), # <--- Clau per absorbir la sobredisp.
method = "REML" # <--- Molt recomenable per a Tweedie
)
fit.gam.tw2
##
## Family: Tweedie(p=1.352)
## Link function: log
##
## Formula:
## egg.count ~ s(lon, lat, bs = "ts", k = 100) + s(b.depth, bs = "ts") +
## s(c.dist, bs = "ts") + s(salinity, bs = "ts") + s(temp.surf,
## bs = "ts") + s(temp.20m, bs = "ts")
##
## Estimated degrees of freedom:
## 32.2253 2.7001 0.9388 0.0009 0.0006 4.0685 total = 40.93
##
## REML score: 941.3792
Observem que els termes s(salinity) i
s(temp.surf) amb \(edf\)
nul, són redundants per al model (\(edf\approx0\)), mentre el terme
s(c.dist)1 no és nul, però té un valor d’edf proper a
1, que ens fa dubtar si convertir-lo en terme lineal.
Per acabar de decidir representarem, el gràfic d’efectes
parcials per veure com queda representat el terme
c.dist
par(mfrow= c(2,2))
plot(fit.gam.tw2, select = 1)
plot(fit.gam.tw2, select = 2)
plot(fit.gam.tw2, select = 3)
plot(fit.gam.tw2, select = 6)
El terme c.dist queda representat per una línia perfecta
de tendència negativa. Això significa que:
La doble penalització ja va fer la selecció: En activar
select = TRUE o fer servir splines d’encongiment
bs= "ts", com en el nostre cas, mgcv descompon
el spline en una part lineal (l’espai nul) i una part no
lineal. L’algorisme ha penalitzat la part no lineal fins a
reduir-la a zero i, a més, ha encongit lleument el pendent
lineal (per això l’edf va caure de 1.0 a 0.9). Si es canviés manualment
a un terme lineal clàssic (+x), s’eliminaria aquesta petita penalització
sobre el pendent, forçant un edf exacte de 1.0 i alterant el criteri
d’optimització del model.
Cal destacar a més que l’enfocament modern de modelatge amb splines penalitzats defensa que és millor deixar que l’estimador REML o GCV decideixi la complexitat de manera contínua. Passar la variable a lineal de forma manual és fer “selecció de models a ull”, la qual cosa invalida en part els p-valors generals del model a causa del biaix de selecció.
Per tant, podem concloure que variable c.dist s’ha
modelat inicialment mitjançant un spline suavitzat penalitzat
(bs="ts"). El procediment de selecció per encongiment
(shrinkage) de mgcv ha reduït els seus graus de llibertat
efectius a \(edf = 0.94\)**, demostrant
un efecte purament lineal. Aquest efecte va resultar ser altament
significatiu \((p < 0.001)\),
mostrant una relació constant i negativa respecte a la variable de
resposta.
Per tant, no modificarem la fórmula de l’ajustament, passant
c.dist com a terme lineal del model.
family=tw()El model definitiu serà per tant el reduït
fit.gam.tw3 <- mgcv::gam(egg.count ~s(lon,lat,bs="ts",k=100)+
s(b.depth,bs="ts")+
s(c.dist,bs="ts")+
s(temp.20m,bs="ts", k=20), # k: Mejora intr. ex-post
data = mack,
family = tw(), # <--- Clau per absorbir la sobredisp.
method = "REML" # <--- Molt recomenable per a Tweedie
)
summary(fit.gam.tw3)
##
## Family: Tweedie(p=1.333)
## Link function: log
##
## Formula:
## egg.count ~ s(lon, lat, bs = "ts", k = 100) + s(b.depth, bs = "ts") +
## s(c.dist, bs = "ts") + s(temp.20m, bs = "ts", k = 20)
##
## Parametric coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 1.05517 0.06845 15.41 <2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Approximate significance of smooth terms:
## edf Ref.df F p-value
## s(lon,lat) 51.0391 99 2.563 < 2e-16 ***
## s(b.depth) 3.1808 9 2.355 4.63e-06 ***
## s(c.dist) 0.9941 9 1.138 1.74e-06 ***
## s(temp.20m) 6.2944 19 1.438 1.11e-05 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## R-sq.(adj) = 0.707 Deviance explained = 80.7%
## -REML = 1584.9 Scale est. = 3.1819 n = 634
Amb tots els temes amb molt alta significació i un nivell de deviància explicada del 80.7%.
par(mfrow=c(2,2))
mgcv::gam.check(fit.gam.tw3)
##
## Method: REML Optimizer: outer newton
## full convergence after 7 iterations.
## Gradient range [-8.259072e-06,5.662976e-07]
## (score 1584.878 & scale 3.181924).
## Hessian positive definite, eigenvalue range [0.440546,443.7984].
## Model rank = 137 / 137
##
## Basis dimension (k) checking results. Low p-value (k-index<1) may
## indicate that k is too low, especially if edf is close to k'.
##
## k' edf k-index p-value
## s(lon,lat) 99.000 51.039 0.85 0.035 *
## s(b.depth) 9.000 3.181 0.93 0.850
## s(c.dist) 9.000 0.994 0.89 0.365
## s(temp.20m) 19.000 6.294 0.79 <2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Veiem com millora la dispersió: el gràfic és molt més acceptable. Amb un nivell de dispersió més baixa i homoscedasticitat acceptable.
El biaix a la dreta de l’histograma, s’explica per vàries raons:
La cua llarga cap a la dreta representa els residus dels llances on vas trobar “superagregacions” o pegats massius d’ous. Si el model va predir una densitat alta (per exemple, 500 ous) basats en la temperatura i geografia, però en el llanci real vas capturar 3000 ous, el residu serà un nombre positiu molt gran. Com que aquests esdeveniments extrems són pocs però intensos, dibuixen aquesta cua allargada cap a la dreta.
Els residus estandarditzats (deviància o Pearson) d’un model
Tweedie no han de ser perfectament simètrics ni normals a
l’histograma si les dades originals tenen un component discret (els
zeros) i un component continu (els recomptes alts). El que és
veritablement crucial és que al QQ-plot, els punts segueixin la línia
diagonal general amb desviacions lleus als extrems.
El \(edf\) s’a plantat a 6.29 (molt
lluny del límit de 19), però el test dóna tres asteriscs amb un
k-index baix (0.79). L’explicació real: Quan l’\(edf\) no augmenta però el p-valor del test
de bases cau a zero, el problema ja no és la manca de flexibilitat \((k)\). El que està passant és que
hi ha autocorrelació residual o un problema de dependència
espacial/temporal a la temperatura. En haver-hi llançaments de
pesca molt propers entre si que tenen temperatures idèntiques i
recomptes d’ous similars (o molts zeros junts), el test de residus
independents de gam.check() es trenca i
dóna un fals positiu (asteriscs).
Per tant podem concloure que el model definitiu de l’anàlisi de la posta d’ous de verat a les costes atèntiques d’Europa és
mgcv::gam(
egg.count ~
s(lon,lat,bs="ts",k=100)+
s(b.depth,bs="ts")+
s(c.dist,bs="ts")+
s(temp.20m,bs="ts"),
data = mack, family = tw(), method = "REML"
)
Si haguéssim de filar extremadament fi, per netejar els asteriscs causats per l’autocorrelació, la solució teòrica seria migrar a un model GAMM (Models Additius Generalitzats Mixts) usant altres llibreries (veure Models mixts (LMM, GLMM, GAMM) en ecologia per afegir una estructura de correlació espacial.
Tot i això, és veritat que per a la majoria de publicacions i
informes científics d’avaluació d’estocs, l’estructura actual amb
mgcv::gam i method="REML és perfectament
acceptable i robusta.
Detall ecològic important: c.dist és el el
valor de la distància des de la ubicació de la mostra fins a la
isòbata (és a dir, la línea de nivell de profunditat) de 200 m
mesurada en graus com si els graus de latitud fossin iguals als graus de
longitud, cosa que en realitat no és així. Context
ecològic: Els verats utilitzen molt la plataforma continental
europea per a la desova. La línia de contorn de 200 metres és un límit
ecològic crític on la plataforma poc profunda s’endinsa a l’oceà
profund. Mesurar la distància fins a aquest límit ajuda a modelar on és
més probable que els verats ponguin ous.↩︎