Modélisation par équations structurelles (SEM) avec R
Autoformation
S’autoformer en statistique via des tutoriels et des capsules vidéo
Modélisation par équations structurelles (SEM) avec R
Ce tutoriel a pour objectif de vous initier aux modélisations par équations structurelles (ou SEM pour « Structural Equation Modelling »), soit une méthode statistique qui permet d’intégrer différentes analyses statistiques telles que les analyses de trajectoires, les modérations, les médiations, les analyses factorielles, l’analyse acheminatoire et plus encore.
Les analyses de ce tutoriel seront exécutées sur R. Pour vous pratiquer, vous pouvez télécharger les données (fichier CSV) utilisées dans ce tutoriel !
Utilité des SEM
Les SEM sont généralement utilisées pour répondre à des questions de recherche estimant une relation linéaire (p. ex., une régression ou une médiation) entre des variables exogènes (c.-à-d., indépendantes) et des variables endogènes (c.-à-d., dépendantes ou prédites). Elles permettent également d’inclure des construits multidimensionnels qui ne peuvent être directement observés dans un échantillon (p. ex., les intentions de quitter une organisation), soit des variables latentes. Ces variables sont mesurées via des indicateurs observables théoriquement sous-jacents au construit en question. Les variables latentes seront approfondies dans la section sur les analyses factorielles confirmatoires.
Une grande force des SEM est leur capacité à examiner des modèles d’une complexité plus pointue. Par exemple, en ajoutant des variables médiatrices ou modératrices, celles-ci nous informent sur les lien directs et indirects (via un médiateur ou modérateur) des variables exogènes sur les variables endogènes. Toutefois, par principe de simplicité, ce tutoriel explorera seulement un modèle de régression dans lequel la variable endogène est latente.
Pour les fins de ce tutoriel, nous examinerons le modèle suivant :
Tel que mentionné ci-haut, une variable latente n’est pas directement mesurée dans l’échantillon et correspond plutôt à une combinaison de divers indicateurs qui eux sont empiriquement mesurés. Le facteur latent permet d’expliquer la covariance entre les indicateurs observés. Les indicateurs sont illustrés dans la figure ci-dessous. Chaque indicateur a un loading qui définit l’importance de cet indicateur observé pour la variable latente d’intérêt. Idéalement, les loadings sont tous positifs et près de 1.
Étapes de l'analyse SEM
Deux grandes étapes sont nécessaires afin de tester adéquatement ce modèle : l’analyse factorielle confirmatoire de la variable latente et la spécification du modèle SEM.
Toutefois, débutons par appeler les packages qui nous seront utiles et importer notre jeu de données. La librairie que nous utilisations en R pour les SEM s’appelle lavaan, qui tire son nom de « latent variable analysis ».
#Appel de notre jeu de données
library(lavaan)
library(readr)
df_SEM <- read_csv(file.choose())
View(df_SEM)
#Retirer les données manquantes et standardiser les données pour analyse SEM
df_SEM <- na.omit(df_SEM) #si la taille de votre échantillon le permet
df_SEM_S <- scale(df_SEM)|> as.data.frame()
Des analyses préliminaires peuvent également être exécutées afin d’avoir un meilleur aperçu des données avec lesquelles nous allons jouer.
#Moyennes, écarts-types et corrélations de nos variables mesurées, nonstandardisées
round(colMeans(jd_SEM_NS, na.rm = TRUE)
round(sd(df_SEM $Bonus), 3)
round(sd(df_SEM $Basepay), 3)
round(sd(df_SEM $QUIT1), 3)
round(sd(df_SEM $QUIT2), 3)
round(sd(df_SEM $QUIT3), 3)
round(sd(df_SEM $QUIT4), 3)
round(sd(df_SEM $QUIT5), 3)
round(cor(df_SEM),3)
1) Analyse factorielle confirmatoire (CFA)
Kline (2015) suggère de vérifier la qualité de mesure des variables latentes comprises dans une SEM à l’aide d’une CFA, soit une analyse statistique qui cherche à détecter la structure latente qui sous-tend les relations entre les indicateurs observés. Il faut donc performer une CFA pour vérifier la qualité de mesure de la variable Intentions de quitter qui est nommée QUIT_tot dans notre jeu de données. Cette vérification est faite à l’aide du code suivant :
QUIT_Model_VL <- '#Variable latente
QUIT_tot =~ QUIT1 + QUIT2 + QUIT3 + QUIT4 +QUIT5'
fit_VL <- cfa(QUIT_Model_VL, data = df_SEM_S)
summary(fit_VL, standardized = TRUE, fit.measures = TRUE, rsquare = TRUE)
Comment pouvons-nous savoir si la qualité de notre mesure est adéquate?
- Vérification des indices d’ajustements :
- Chi-carré (χ²)
- Ne devrait pas être significatif
- Indice moins pertinent lorsque notre N est élevé (n > 200) car il sera très souvent significatif
- CFI et TLI
- Grandes valeurs indiquent un meilleur ajustement
- Seuil recherché > .95 pour un très bon ajustement (Caron, 2018)
- RMSEA et SRMR
- Petites valeurs indiquent un meilleur ajustement
- Seuil minimal recherché d’environ .08, idéalement < .06. (Caron, 2018)
- La valeur des loadings standardisés des indicateurs face à la variable latente
- Le seuil souhaité est généralement .70
- Le pourcentage de variance des indicateurs expliqué par le construit latent
- Le seuil souhaité est généralement 50%
- Chi-carré (χ²)
Model Test User Model:
Test statistic 475.454
Degrees of freedom 5
P-value (Chi-square) 0.000
Model Test Baseline Model:
Test statistic 3908.058
Degrees of freedom 10
P-value 0.000
User Model versus Baseline Model:
Comparative Fit Index (CFI) 0.879
Tucker-Lewis Index (TLI) 0.759
Loglikelihood and Information Criteria:
Loglikelihood user model (H0) -1821.447
Loglikelihood unrestricted model (H1) -1583.720
Akaike (AIC) 3662.894
Bayesian (BIC) 3705.020
Sample-size adjusted Bayesian (SABIC) 3673.280
Root Mean Square Error of Approximation:
RMSEA 0.434
90 Percent confidence interval - lower 0.402
90 Percent confidence interval - upper 0.468
P-value H_0: RMSEA <= 0.050 0.000
P-value H_0: RMSEA >= 0.080 1.000
Standardized Root Mean Square Residual:
SRMR 0.057
Parameter Estimates:
Standard errors Standard
Information Expected
Information saturated (h1) model Structured
Latent Variables:
Estimate Std.Err z-value P(>|z|) Std.lv Std.all
QUIT_tot =~
QUIT1 1.000 0.892 0.893
QUIT2 0.959 0.034 28.231 0.000 0.856 0.857
QUIT3 1.105 0.027 41.571 0.000 0.986 0.987
QUIT4 0.983 0.033 29.817 0.000 0.877 0.878
QUIT5 1.094 0.027 40.294 0.000 0.976 0.977
Variances:
Estimate Std.Err z-value P(>|z|) Std.lv Std.all
.QUIT1 0.202 0.014 14.831 0.000 0.202 0.202
.QUIT2 0.266 0.018 15.130 0.000 0.266 0.266
.QUIT3 0.027 0.004 6.139 0.000 0.027 0.027
.QUIT4 0.229 0.015 14.982 0.000 0.229 0.230
.QUIT5 0.045 0.005 9.220 0.000 0.045 0.045
QUIT_tot 0.796 0.062 12.830 0.000 1.000 1.000
R-Square:
Estimate
QUIT1 0.798
QUIT2 0.734
QUIT3 0.973
QUIT4 0.770
QUIT5 0.955
Les résultats illustrés dans la boîte ci-dessus indiquent que l’ajustement de notre mesure n’est pas adéquat. En effet, le CFI, le TLI et le RMSEA n’étant pas satisfaisants, il semble nécessaire de voir comment il est possible de modifier notre modèle pour que l’ajustement s’améliore, tout en gardant une bonne partie de la variance des indicateurs expliquée par le facteur latent et en s’assurant que les loadings standardisés de chaque indicateur soient supérieurs à .70.
Pour ce faire, R peut proposer différentes modifications possibles, en ordre de pertinence, pour améliorer l’ajustement de notre modèle avec la fonction modindices. Parmi les modifications proposées, il est désirable de choisir des modifications qui se justifient théoriquement ou qui ont du sens en lisant les items du questionnaire. Une fois les modifications ajoutées au modèle, il ne reste qu’à tester ce deuxième modèle et voir si l’ajustement est maintenant plus adéquat.
#Vérifier comment avoir un meilleur ajustement
modindices(fit_VL, sort = TRUE, maximum.number = 10)
lhs op rhs mi epc sepc.lv sepc.all sepc.nox
QUIT3 ~~ QUIT5 560.237 0.201 0.201 5.771 5.771
QUIT1 ~~ QUIT4 188.450 0.141 0.141 0.657 0.657
QUIT1 ~~ QUIT2 152.248 0.136 0.136 0.586 0.586
QUIT2 ~~ QUIT4 148.422 0.142 0.142 0.575 0.575
QUIT4 ~~ QUIT5 54.597 -0.049 -0.049 -0.479 -0.479
#Tester le second modèle
QUIT_Model_VL2 <- 'QUIT_tot =~ QUIT1 + QUIT2 + QUIT3 + QUIT4 +QUIT5
QUIT3 ~~ QUIT5'
fit_VL2 <- cfa(QUIT_Model_VL2, data = df_SEM_S)
summary(fit_VL2, standardized = TRUE, fit.measures = TRUE, rsquare = TRUE)
Vous remarquez que les nouveaux indices d’ajustement sont pratiquement tous parfaits (χ²(4) = 2.48, p = .65; CFI = 1.00 ; TLI = 1.00 ; RMSEA = .000 ; SRMR = .003. Ces indices sont tirés d’un jeu de données que nous avons créé pour les fins de ce tutoriel et ne sont pas réalistes. Toutefois, puisqu’ils indiquent un « excellent ajustement, » nous poursuivrons ainsi avec notre modèle SEM complet.
2) Spécification du modèle
Une fois la qualité de notre variable latente vérifiée, nous sommes prêts à spécifier notre modèle d’analyse principale. Cela peut être fait avec l’aide du code ci-dessous. Nous pouvons ajouter des régressions en utilisant l’opérateur « ~ » de lavaan, en utilisant la forme : y ~ x1 + x2 + …
#Spécification du modèle
QUIT_Model <- '#variable latente
QUIT_tot =~ QUIT1 + QUIT2 + QUIT3 + QUIT4 +QUIT5
QUIT3 ~~ QUIT5
#regressions
QUIT_tot ~ Bonus + Basepay'
#Calculer le fit du modèle et faire un résumer
fit <- sem(QUIT_Model, data = df_SEM_S)
summary(fit, standardized = TRUE, fit.measures = TRUE, rsquare = TRUE)
Puisque notre modèle est assez simple et ne comprend qu’une régression multiple, les indices d’ajustement restent les mêmes dans notre modèle complet. Dans cette nouvelle étape, il faut donc regarder comment nos deux variables exogènes influencent notre variable endogène, soit les intentions de quitter.
Tel qu’indiqué dans la boîte ci-dessous, seulement 6% de la variance des intentions de quitter est expliquée par nos deux prédicteurs, soit le salaire de base et les bonus. Cela a du sens considérant tous les autres facteurs pouvant influencer ce souhait de rester ou de changer d’organisation (p. ex., quête de développement professionnel, contexte de vie personnel, etc.). Les résultats indiquent également que les bonus prédisent positivement les intentions de quitter (β = .360, p < .001) alors que le salaire de base les prédit négativement (β = -.218, p = .001).
#Seulement le output de la régression est inclus dans cette boîte.
Regressions:
Estimate Std.Err z-value P(>|z|) Std.lv Std.all
QUIT_tot ~
Bonus 0.345 0.065 5.334 0.000 0.360 0.360
Basepay -0.209 0.065 -3.232 0.001 -0.218 -0.218
Covariances:
Estimate Std.Err z-value P(>|z|) Std.lv Std.all
.QUIT3 ~~
.QUIT5 0.172 0.014 12.441 0.000 0.172 0.858
Variances:
Estimate Std.Err z-value P(>|z|) Std.lv Std.all
.QUIT1 0.080 0.008 9.462 0.000 0.080 0.080
.QUIT2 0.144 0.011 12.586 0.000 0.144 0.144
.QUIT3 0.185 0.014 13.445 0.000 0.185 0.185
.QUIT4 0.102 0.009 10.934 0.000 0.102 0.103
.QUIT5 0.218 0.016 13.835 0.000 0.218 0.218
.QUIT_tot 0.864 0.060 14.472 0.000 0.941 0.941
R-Square:
Estimate
QUIT1 0.920
QUIT2 0.856
QUIT3 0.815
QUIT4 0.897
QUIT5 0.782
QUIT_tot 0.059
Syntaxe complète
#Importation du jeu de données
library(lavaan)
library(readr)
df_SEM <- read_csv(file.choose())
View(df_SEM)
#Retirer les données manquantes et standardiser les données pour analyse SEM
df_SEM <- na.omit(df_SEM) #si la taille de votre échantillon le permet
df_SEM_S <- scale(df_SEM)|> as.data.frame()
#Analyses descriptives pour avoir un aperçu du jeu de données (moyennes, SD, corrélations)
round(colMeans(df_SEM, na.rm = TRUE))
round(sd(df_SEM $Bonus), 3)
round(sd(df_SEM $Basepay), 3)
round(sd(df_SEM $QUIT1), 3)
round(sd(df_SEM $QUIT2), 3)
round(sd(df_SEM $QUIT3), 3)
round(sd(df_SEM $QUIT4), 3)
round(sd(df_SEM $QUIT5), 3)
round(cor(df_SEM),3)
#CFA
QUIT_Model_VL <- '#variable latente
QUIT_tot =~ QUIT1 + QUIT2 + QUIT3 + QUIT4 +QUIT5'
fit_VL <- cfa(QUIT_Model_VL, data = df_SEM_S)
summary(fit_VL, standardized = TRUE, fit.measures = TRUE, rsquare = TRUE)
#Vérifier comment avoir un meilleur ajustement
modindices(fit_VL, sort = TRUE, maximum.number = 10)
#Tester le second modèle
QUIT_Model_VL2 <- 'QUIT_tot =~ QUIT1 + QUIT2 + QUIT3 + QUIT4 +QUIT5
QUIT3 ~~ QUIT5'
fit_VL2 <- cfa(QUIT_Model_VL2, data = df_SEM_S)
summary(fit_VL2, standardized = TRUE, fit.measures = TRUE, rsquare = TRUE)
#Spécification du modèle
QUIT_Model <- '#variable latente
QUIT_tot =~ QUIT1 + QUIT2 + QUIT3 + QUIT4 +QUIT5
QUIT3 ~~ QUIT5
#regressions
QUIT_tot ~ Bonus + Basepay'
#Calculer le fit du modèle et faire un résumer
fit <- sem(QUIT_Model, data = df_SEM_S)
summary(fit, standardized = TRUE, fit.measures = TRUE, rsquare = TRUE)
Références
- Caron, P.-O. (2018). La modélisation par équations structurelles avec Mplus (Ser. Mesure et évaluation, 8). Presses de l’Université du Québec.
- Kline, R. B. (2015). Principles and practice of structural equation modeling. Guilford publications.
PARTAGEZ VOS IMPRESSIONS & POSEZ VOS QUESTIONS ICI !