library("sf")
library("terra")
library("dplyr")
library("readr")
library("ggplot2")
library("PerformanceAnalytics")
library("pastecs")
library("lme4")
library("bbmle")
library("MuMIn")
library("MASS")
Variablenselektion Multivariate Modelle
Libraries laden
Variablenselektion
→ Vorgehen analog Coppes u. a. (2017)
Aufgabe 1
Mit dem folgenden Code kann eine simple Korrelationsmatrix aufgebaut werden, vergl. Aufgabe 5 vorangehende Woche
<- read_delim("datasets/fallstudie_n/Aufgabe4_Datensatz_Habitatnutzung_Modelle_241028.csv", delim = ";")
DF_mod
<- DF_mod |>
DF_mod_day filter(time_of_day == "day")
round(cor(DF_mod_day[, 5:12], method = "pearson"), 2)
## slope topo_pos dist_road_trails dist_road_only dist_sett
## slope 1.00 0.09 0.31 0.34 0.14
## topo_pos 0.09 1.00 0.06 0.09 0.08
## dist_road_trails 0.31 0.06 1.00 0.93 -0.05
## dist_road_only 0.34 0.09 0.93 1.00 -0.08
## dist_sett 0.14 0.08 -0.05 -0.08 1.00
## forest_prop 0.29 0.01 -0.03 -0.05 0.50
## us_2014 0.28 -0.04 0.03 0.04 0.06
## os_2014 0.45 0.06 -0.03 -0.01 0.34
## forest_prop us_2014 os_2014
## slope 0.29 0.28 0.45
## topo_pos 0.01 -0.04 0.06
## dist_road_trails -0.03 0.03 -0.03
## dist_road_only -0.05 0.04 -0.01
## dist_sett 0.50 0.06 0.34
## forest_prop 1.00 0.34 0.76
## us_2014 0.34 1.00 0.47
## os_2014 0.76 0.47 1.00
# hier kann die Schwelle für die Korrelation gesetzt werden, 0.7 ist eher liberal /
# 0.5 konservativ
<- round(cor(DF_mod_day[, 5:12], method = "pearson"), 2)
cor abs(cor) < 0.7] <- 0
cor[
cor## slope topo_pos dist_road_trails dist_road_only dist_sett
## slope 1 0 0.00 0.00 0
## topo_pos 0 1 0.00 0.00 0
## dist_road_trails 0 0 1.00 0.93 0
## dist_road_only 0 0 0.93 1.00 0
## dist_sett 0 0 0.00 0.00 1
## forest_prop 0 0 0.00 0.00 0
## us_2014 0 0 0.00 0.00 0
## os_2014 0 0 0.00 0.00 0
## forest_prop us_2014 os_2014
## slope 0.00 0 0.00
## topo_pos 0.00 0 0.00
## dist_road_trails 0.00 0 0.00
## dist_road_only 0.00 0 0.00
## dist_sett 0.00 0 0.00
## forest_prop 1.00 0 0.76
## us_2014 0.00 1 0.00
## os_2014 0.76 0 1.00
Aufgabe 2
Skalieren der Variablen, damit ihr Einfluss vergleichbar wird (Befehl scale(); Problem verschiedene Skalen der Variablen (bspw. Neigung in Grad, Distanz in Metern)); Umwandeln der Reh-ID in einen Faktor, damit dieser als Random Factor ins Model eingespiesen werden kann.
<- DF_mod_day |>
DF_mod_day mutate(
slope_scaled = scale(slope),
topo_pos_scaled = scale(topo_pos),
us_scaled = scale(us_2014),
os_scaled = scale(os_2014),
forest_prop_scaled = scale(forest_prop),
dist_road_trails_scaled = scale(dist_road_trails),
dist_road_only_scaled = scale(dist_road_only),
dist_sett_scaled = scale(dist_sett),
id = as.factor(id)
)
Aufgabe 3
Selektion der Variablen in einem univariaten Model
Ein erstes GLMM (Generalized Linear Mixed Effects Modell) aufbauen: Funktion und Modelformel
wichtige Seite auf der man viele Hilfestellungen zu GLMM’s finden kann.
# wir werden das package lme4 mit der Funktion glmer verwenden
# die Hilfe von glmer aufrufen: ?glmer
# glmer(formula, data = , family = binomial)
# 1) formula:
# Abhängige Variable ~ Erklärende Variable + Random Factor
# In unseren Modellen kontrollieren wir für individuelle Unterschiede bei den Rehen
# indem wir einen Random Factor definieren => (1 | id)
# 2) data:
# euer Datensatz
# 3) family:
# hier binomial
# warum binomial? Verteilung Daten der abhängigen Variable Präsenz/Absenz
ggplot(DF_mod_day, aes(pres_abs)) +
geom_histogram()
# --> Binäre Verteilung => Binomiale Verteilung mit n = 1
# und wie schaut die Verteilung der Daten der abhängigen Variable Nutzungsintensität
# (nmb, werden wir in diesem Kurs aber nicht genauer anschauen) aus?
Aufgabe 4
Mit der GLMM Formel bauen wir in einem ersten Schritt eine univariate Variablenselektion auf.
Als abhängige Variable verwenden wir die Präsenz/Absenz der Rehe in den Kreisen
# Die erklärende Variable in m1 ist die erste Variable der korrelierenden Variablen
# Die erklärende Variable in m2 ist die zweite Variable der korrelierenden Variablen
<- glmer(Abhaengige_Variable ~ Erklaerende_Variable + (1 | id),
modell_1 data = DF_mod_day,
family = binomial
)
<- glmer(Abhaengige_Variable ~ Erklaerende_Variable + (1 | id),
modell_2 data = DF_mod_day,
family = binomial
)
# mit dieser Funktion können die Modellergebnisse inspiziert werden
summary(modell_1)
summary(modell_2)
# Mit dieser Funktion kann der Informationgehalt der beiden Modelle gegeneinander
# abgeschätzt werden
::AICtab(modell_1, modell_2)
bbmle
# tieferer AIC -> besser (AIC = Akaike information criterion)
# ==> dieses Vorgehen muss nun für alle korrelierten Variablen für jeden Teildatensatz
# (Tag/Nacht) durchgeführt werden, um nur noch nicht (R < 0.7) korrelierte Variablen
# in das Modell einfliessen zu lassen
Musterlösung
<- glmer(pres_abs ~ dist_road_trails_scaled + (1 | id), data = DF_mod_day, family = binomial)
modell_1 <- glmer(pres_abs ~ dist_road_only_scaled + (1 | id), data = DF_mod_day, family = binomial)
modell_2
summary(modell_1)
## Generalized linear mixed model fit by maximum likelihood (Laplace
## Approximation) [glmerMod]
## Family: binomial ( logit )
## Formula: pres_abs ~ dist_road_trails_scaled + (1 | id)
## Data: DF_mod_day
##
## AIC BIC logLik deviance df.resid
## 5104.9 5123.7 -2549.4 5098.9 3961
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -2.1046 -0.7564 -0.6277 1.0812 1.9219
##
## Random effects:
## Groups Name Variance Std.Dev.
## id (Intercept) 0.1996 0.4467
## Number of obs: 3964, groups: id, 12
##
## Fixed effects:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -0.31120 0.13418 -2.319 0.0204 *
## dist_road_trails_scaled 0.37745 0.03848 9.808 <2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr)
## dst_rd_trl_ -0.004
summary(modell_2)
## Generalized linear mixed model fit by maximum likelihood (Laplace
## Approximation) [glmerMod]
## Family: binomial ( logit )
## Formula: pres_abs ~ dist_road_only_scaled + (1 | id)
## Data: DF_mod_day
##
## AIC BIC logLik deviance df.resid
## 5098.4 5117.2 -2546.2 5092.4 3961
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -1.9625 -0.7615 -0.6080 1.0579 1.9425
##
## Random effects:
## Groups Name Variance Std.Dev.
## id (Intercept) 0.2103 0.4586
## Number of obs: 3964, groups: id, 12
##
## Fixed effects:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -0.3024 0.1375 -2.199 0.0279 *
## dist_road_only_scaled 0.3950 0.0389 10.154 <2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr)
## dst_rd_nly_ 0.002
::AICtab(modell_1, modell_2)
bbmle## dAIC df
## modell_2 0.0 3
## modell_1 6.5 3
# tieferer AIC -> besser (AIC = Akaike information criterion) -> als deltaAIC ausgewiesen
# Distanz zu Strassen (dist_road_only) = besser
<- glmer(pres_abs ~ forest_prop_scaled + (1 | id), data = DF_mod_day, family = binomial)
modell_3 <- glmer(pres_abs ~ os_scaled + (1 | id), data = DF_mod_day, family = binomial)
modell_4
summary(modell_3)
## Generalized linear mixed model fit by maximum likelihood (Laplace
## Approximation) [glmerMod]
## Family: binomial ( logit )
## Formula: pres_abs ~ forest_prop_scaled + (1 | id)
## Data: DF_mod_day
##
## AIC BIC logLik deviance df.resid
## 4726.1 4745.0 -2360.1 4720.1 3961
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -2.2952 -0.7853 -0.3909 0.9056 3.4113
##
## Random effects:
## Groups Name Variance Std.Dev.
## id (Intercept) 0.3069 0.554
## Number of obs: 3964, groups: id, 12
##
## Fixed effects:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -0.4351 0.1649 -2.639 0.00831 **
## forest_prop_scaled 0.8805 0.0443 19.878 < 2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr)
## frst_prp_sc -0.060
summary(modell_4)
## Generalized linear mixed model fit by maximum likelihood (Laplace
## Approximation) [glmerMod]
## Family: binomial ( logit )
## Formula: pres_abs ~ os_scaled + (1 | id)
## Data: DF_mod_day
##
## AIC BIC logLik deviance df.resid
## 4863.0 4881.9 -2428.5 4857.0 3961
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -2.0044 -0.7984 -0.4421 0.9854 2.8754
##
## Random effects:
## Groups Name Variance Std.Dev.
## id (Intercept) 0.3228 0.5682
## Number of obs: 3964, groups: id, 12
##
## Fixed effects:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -0.34748 0.16847 -2.063 0.0392 *
## os_scaled 0.67559 0.03862 17.494 <2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr)
## os_scaled -0.029
::AICtab(modell_3, modell_4)
bbmle## dAIC df
## modell_3 0.0 3
## modell_4 136.9 3
# tieferer AIC -> besser (AIC = Akaike information criterion) -> als deltaAIC ausgewiesen
# Distanz zu Strassen (dist_road_only) = besser
Aufgabe 5
Selektion der Variablen in einem multivariaten Model
Mit folgendem Code kann eine automatisierte Variablenselektion (dredge-Funktion) und ein Modelaveraging aufgebaut werden (siehe auch Stats-Skript von J.Dengler & Team)
# hier wird die Formel für die dredge-Funktion vorbereitet (die Variablen V1-V6
# sind jene welche nach der univariaten Variablenselektion noch übrig bleiben)
<- pres_abs ~
f +
V1 +
V2 +
V3 +
V4 +
V5
V6
# in diesem Befehl kommt der Random-Factor (das Reh) hinzu und es wird eine Formel
# daraus gemacht
<- paste(c(f, "+ (1 | id)"), collapse = " ") |> as.formula()
f_dredge
# Das Modell mit dieser Formel ausführen
<- glmer(f_dredge, data = DF_mod_day, family = binomial, na.action = "na.fail")
m
# Das Modell in die dredge-Funktion einfügen (siehe auch unbedingt ?dredge)
<- dredge(m)
all_m
all_m
# Importance values der einzelnen Variablen (Gibt an, wie bedeutsam eine bestimmte
# Variable ist, wenn man viele verschiedene Modelle vergleicht (multimodel inference))
sw(all_m)
# Schlussendlich wird ein Modelaverage durchgeführt (Schwellenwert für das delta-AIC = 2)
<- model.avg(all_m, rank = "AICc", subset = delta < 2)
avgmodel summary(avgmodel)
# ==> für den Nachtdatensatz muss der gleiche Prozess der Variablenselektion
# durchgespielt werden.
Musterlösung
# hier wird die Formel für die dredge-Funktion vorbereitet (die Variablen V1-V6
# sind jene welche nach der univariaten Variablenselektion noch übrig bleiben)
<- pres_abs ~
f +
slope_scaled +
topo_pos_scaled +
us_scaled +
forest_prop_scaled +
dist_road_only_scaled
dist_sett_scaled
# in diesem Befehl kommt der Random-Factor (das Reh) hinzu und es wird eine Formel
# daraus gemacht
<- paste(c(f, "+ (1 | id)"), collapse = " ") |> as.formula()
f_dredge
# Das Modell mit dieser Formel ausführen
<- glmer(f_dredge, data = DF_mod_day, family = binomial, na.action = "na.fail")
m
# Das Modell in die dredge-Funktion einfügen (siehe auch unbedingt ?dredge)
<- dredge(m)
all_m
# Importance values der einzelnen Variablen (Gibt an, wie bedeutsam eine bestimmte
# Variable ist, wenn man viele verschiedene Modelle vergleicht (multimodel inference))
sw(all_m)
## dist_road_only_scaled forest_prop_scaled us_scaled
## Sum of weights: 1.00 1.00 1.00
## N containing models: 32 32 32
## slope_scaled dist_sett_scaled topo_pos_scaled
## Sum of weights: 0.99 0.46 0.30
## N containing models: 32 32 32
# Schlussendlich wird ein Modelaverage durchgeführt (Schwellenwert für das delta-AIC = 2)
<- model.avg(all_m, rank = "AICc", subset = delta < 2)
avgmodel summary(avgmodel)
##
## Call:
## model.avg(object = get.models(object = all_m, subset = delta <
## 2), rank = "AICc")
##
## Component model call:
## glmer(formula = pres_abs ~ <4 unique rhs>, data = DF_mod_day, family =
## binomial, na.action = na.fail)
##
## Component models:
## df logLik AICc delta weight
## 1346 6 -2268.17 4548.37 0.00 0.38
## 12346 7 -2267.34 4548.71 0.34 0.32
## 13456 7 -2268.01 4550.04 1.68 0.16
## 123456 8 -2267.16 4550.35 1.98 0.14
##
## Term codes:
## dist_road_only_scaled dist_sett_scaled forest_prop_scaled
## 1 2 3
## slope_scaled topo_pos_scaled us_scaled
## 4 5 6
##
## Model-averaged coefficients:
## (full average)
## Estimate Std. Error Adjusted SE z value Pr(>|z|)
## (Intercept) -0.432191 0.139554 0.139597 3.096 0.00196 **
## dist_road_only_scaled 0.416554 0.046861 0.046875 8.886 < 2e-16 ***
## forest_prop_scaled 0.818821 0.057266 0.057282 14.295 < 2e-16 ***
## slope_scaled -0.158651 0.049230 0.049245 3.222 0.00127 **
## us_scaled 0.390805 0.041070 0.041083 9.513 < 2e-16 ***
## dist_sett_scaled -0.036839 0.058045 0.058054 0.635 0.52571
## topo_pos_scaled 0.006678 0.022846 0.022852 0.292 0.77013
##
## (conditional average)
## Estimate Std. Error Adjusted SE z value Pr(>|z|)
## (Intercept) -0.43219 0.13955 0.13960 3.096 0.00196 **
## dist_road_only_scaled 0.41655 0.04686 0.04688 8.886 < 2e-16 ***
## forest_prop_scaled 0.81882 0.05727 0.05728 14.295 < 2e-16 ***
## slope_scaled -0.15865 0.04923 0.04924 3.222 0.00127 **
## us_scaled 0.39081 0.04107 0.04108 9.513 < 2e-16 ***
## dist_sett_scaled -0.08030 0.06208 0.06210 1.293 0.19597
## topo_pos_scaled 0.02197 0.03717 0.03718 0.591 0.55451
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Musterlösung
#| eval: false
#| error: true
#| echo: false
# hier wird die Formel für die dredge-Funktion vorbereitet (die Variablen V1-V8
# sind jene welche nach der univariaten Variablenselektion noch übrig bleiben)
<- pres_abs ~
f +
slope_scaled +
topo_pos_scaled +
us_scaled +
os_scaled +
forest_prop_scaled +
dist_road_only_scaled +
dist_road_trails_scaled
dist_sett_scaled
# inn diesem Befehl kommt der Random-Factor (das Reh) hinzu und es wird eine Formel
# daraus gemacht
<- paste(c(f, "+ (1 | id)"), collapse = " ") |> as.formula()
f_dredge
# Das Modell mit dieser Formel ausführen
<- glmer(f_dredge, data = DF_mod_day, family = binomial, na.action = "na.fail")
m
::vif(m)
car## slope_scaled topo_pos_scaled us_scaled
## 1.514328 1.083853 1.242521
## os_scaled forest_prop_scaled dist_road_only_scaled
## 2.626511 2.664066 5.844383
## dist_road_trails_scaled dist_sett_scaled
## 5.674976 1.427576
mean(car::vif(m))
## [1] 2.759777