Cette page web accompagne les quatre premières séances du cours de Méthodes quantitatives pour la sociologie 2 (année universitaire 2015-2016). Elle reprend les codes R utilisés pendant les séances de cours ainsi que des exercices supplémentaires avec solution. L’ensemble des données nécessaires sont accessibles à l’adresse http://teaching.slmc.fr/mqs2/.
Télécharger le support complet du cours en version imprimable (en date du 27 avril 2016)
Télécharger le document de travail de l’Insee sur la régression logistique (de Cédric Afsa, paru en mars 2016)
Cette page a été conçue avec R Markdown sous RStudio et compilée le 2016-05-14 à 15:45:09. Elle peut être enregistrée sous la forme d’un fichier .html
autonome pour être consultée hors connexion.
L’objectif de cette première séance est d’introduire les spécificités des méthodes de régression à partir d’un exemple fictif suivi tout du long : l’analyse de la relation entre poids et activité physique régulière. Le cours procède en trois temps :
L’échantillon de données utilisé a été entièrement simulé à l’aide des fonctions rbinom()
et rnorm()
de R (taper ?rbinom
ou ?rnorm
dans R pour en savoir plus). Ces fonctions font appel à un générateur de nombres pseudo-aléatoires qu’il est possible d’initialiser avec la fonction set.seed()
(lien pour en savoir plus sur la génération de nombres aléatoires sous R)
# Initialisation du générateur de nombres pseudo-aléatoires de R
set.seed(1)
# Taille de l'échantillon simulé
n <- 100
# Simulation des variables
femme <- rbinom(n, 1, 0.5)
sport <- femme*rbinom(n, 1, 0.65) + (1-femme)*rbinom(n,1,0.45)
taille <- (1-femme)*rnorm(n,177,8) + femme*rnorm(n,165,8)
imc <- sport*rnorm(n,22,1) + (1-sport)*rnorm(n,26,1)
poids <- imc*(taille/100)**2
regime <- (imc > 23 + rnorm(n,0,2.5))*1
l.poids <- regime*(poids + rnorm(n,2,2)) + (1-regime)*(poids + rnorm(n,0,2))
# Arrondi pour les variables numériques
taille <- round(taille,0)
poids <- round(poids,0)
l.poids <- round(l.poids,0)
# Affichage des 10 premiers individus
data.frame(poids,taille,sport)[1:10,]
## poids taille sport
## 1 88 181 0
## 2 79 177 0
## 3 61 164 1
## 4 65 163 0
## 5 67 165 0
## 6 69 174 1
## 7 44 146 1
## 8 63 170 1
## 9 71 168 0
## 10 80 192 1
Le poids des individus étant fortement lié à leur taille, on va chercher à contrôler l’effet de la taille dans l’analyse de la relation entre poids et activité physique régulière.
On commence donc par analyser la relation entre le poids et la taille : comme il s’agit de deux variables de nature quantitative, on peut représenter leur association par un nuage de points et la synthétiser à l’aide du coefficient de corrélation linéaire de Pearson.
# Construction du nuage de points
plot(taille,poids,xlab="Taille en cm",ylab="Poids en kg")
# Ajout d'un titre général
title(main="Relation entre le poids et la taille des individus")
# Calcul du coefficient de corrélation avec la fonction cor()
cor(taille,poids)
## [1] 0.8645734
On peut également estimer le modèle de régression linéaire simple suivant: \[\text{(m1)} \quad poids_i = \beta_0 + \beta_1 \times taille_i + \epsilon_i\]
Pour ce faire, on utilise la fonction lm()
: on l’utilise pour effectuer l’estimation puis on stocke ses résultats dans un objet (m1
dans l’exemple) ; la fonction summary
permet ensuite d’afficher une synthèse de ces résultats.
# Estimation du modèle m1 et affectation à l'objet m1
m1 <- lm(poids ~ taille)
# Résumé du modèle m1
summary(m1)
##
## Call:
## lm(formula = poids ~ taille)
##
## Residuals:
## Min 1Q Median 3Q Max
## -17.204 -5.020 1.726 4.492 16.837
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -107.16662 10.46301 -10.24 <2e-16 ***
## taille 1.04095 0.06112 17.03 <2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 6.483 on 98 degrees of freedom
## Multiple R-squared: 0.7475, Adjusted R-squared: 0.7449
## F-statistic: 290.1 on 1 and 98 DF, p-value: < 2.2e-16
En moyenne dans l’échantillon, une taille supérieure de 1 cm est associée à un poids supérieur de 1,04 kg. Les valeurs prédites par le modèle sont stockées dans l’objet m1
et accessibles via l’entrée fitted.value
:
# Récupération et affichage des valeurs prédites par m1
predict1 <- round(m1$fitted.values,2)
data.frame(poids,taille,sport,predict1)[1:10,]
## poids taille sport predict1
## 1 88 181 0 81.24
## 2 79 177 0 77.08
## 3 61 164 1 63.55
## 4 65 163 0 62.51
## 5 67 165 0 64.59
## 6 69 174 1 73.96
## 7 44 146 1 44.81
## 8 63 170 1 69.79
## 9 71 168 0 67.71
## 10 80 192 1 92.70
On peut également récupérer la valeur des coefficients de m1
pour tracer la droite correspondant à ces valeurs prédites :
# Construction du nuage de points
plot(taille,poids,xlab="Taille en cm",ylab="Poids en kg")
# Récupération des valeurs des coefficients avec la fonction (coef())
m1beta0 <- coef(m1)[1]
m1beta1 <- coef(m1)[2]
# Ajout d'une droite d'équation y = m1beta0 + m1beta1 * x
abline(a = m1beta0, b = m1beta1)
# Ajout d'un titre général
title(main="Représentation graphique de la prédiction du modèle 1")
Quand on compare le poids moyen des individus selon qu’ils pratiquent ou non une activité physique régulière, la relation apparaît assez nettement (- 18 kg pour ceux qui pratiquent une activité physique régulière).
data.frame(
sport=c(0,1)
, poids=f(as.numeric(by(poids,sport,mean)))
, taille=f(as.numeric(by(taille,sport,mean)))
)
## sport poids taille
## 1 0 78,76 174,24
## 2 1 60,84 166,76
Cependant, les personnes pratiquant une activité physique régulière étant en moyenne plus petites que les autres (- 8 cm), l’intensité de cette relation serait certainement moins forte si on contrôlait par la taille.
Dans un premier temps, on peut revenir au graphique et y différencier les individus selon qu’ils pratiquent ou non une activité physique régulière.
# Construction du nuage de points
plot(taille,poids,pch=sport,xlab="Taille en cm",ylab="Poids en kg")
# Ajout de la légende
legend("topleft",legend=c("Pas d'activité physique régulière","Activité physique régulière"),pch=c(0,1))
# Ajout d'un titre général
title(main="Poids, taille et activité physique des individus")
Cette représentation semble indiquer l’idée que l’activité physique régulière est associée, à taille égale, à un poids moindre. Pour approfondir cette analyse, on met en oeuvre un modèle de régression multiple : \[\text{(m2)} \quad poids_i = \beta_0 + \beta_1 \times taille_i + \beta_2 \times sport_i + \epsilon_i\] où \(sport_i\) est une variable indicatrice.
# Estimation du modèle m2
m2 <- lm(poids ~ taille + sport)
# Résumé du modèle m2
summary(m2)
##
## Call:
## lm(formula = poids ~ taille + sport)
##
## Residuals:
## Min 1Q Median 3Q Max
## -9.1134 -2.4723 -0.5312 2.4404 13.1832
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -69.48486 6.24333 -11.13 <2e-16 ***
## taille 0.85085 0.03573 23.82 <2e-16 ***
## sport -11.55417 0.76182 -15.17 <2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 3.549 on 97 degrees of freedom
## Multiple R-squared: 0.9251, Adjusted R-squared: 0.9236
## F-statistic: 599 on 2 and 97 DF, p-value: < 2.2e-16
L’estimation du coefficient \(\beta_2\) semble indiquer que la pratique d’une activité physique régulière est associée à un poids moyen d’environ 11,6 kg plus faible. Cette valeur est moindre que les 18 kg qu’indiquaient les statistiques univariées : ceci est dû à l’effet de structure de la taille sur l’activité physique régulière (le fait que dans l’échantillon les personnes qui pratiquent une activité physique régulière mesurent en moyenne 8 cm de moins que les autres).
À nouveau on peut calculer les valeurs prédites par le modèle et les représenter sur le graphique.
predict2 <- round(m2$fitted.values,2)
data.frame(poids,taille,sport,predict1,predict2)[1:10,]
## poids taille sport predict1 predict2
## 1 88 181 0 81.24 84.52
## 2 79 177 0 77.08 81.12
## 3 61 164 1 63.55 58.50
## 4 65 163 0 62.51 69.20
## 5 67 165 0 64.59 70.90
## 6 69 174 1 73.96 67.01
## 7 44 146 1 44.81 43.18
## 8 63 170 1 69.79 63.60
## 9 71 168 0 67.71 73.46
## 10 80 192 1 92.70 82.32
Le modèle étant de meilleure qualité que le précédent, les valeurs prédites sont en général plus proches des valeurs effectives.
# Construction du nuage de points
plot(taille,poids,pch=sport,xlab="Taille en cm",ylab="Poids en kg")
# Ajout des droites représentant la prédiction du modèle m2
abline(a = coef(m2)[1], b = coef(m2)[2])
abline(a = coef(m2)[1] + coef(m2)[3], b = coef(m2)[2],lty=2)
# Ajout d'une légende mixte
legend("topleft",legend=c("Pas d'activité physique régulière","Activité physique régulière"),pch=c(0,1),lty=c(1,2))
# Ajout d'un titre général
title(main="Représentation graphique de la prédiction du modèle 2")
Au-delà de la valeur des coefficients, il est possible d’interpréter la significativité des coefficients à l’aide de leur p-valeur ou d’un intervalle de confiance (cf. le cours).
On cherche enfin à mesurer la relation entre poids et régimes amaigrissants, en contrôlant par la taille et par l’activité physique régulière. Le modèle de régression multiple que l’on estime est donc le suivant : \[\text{(m3)} \quad poids_i = \beta_0 + \beta_1 \times taille_i + \beta_2 \times sport_i + \beta_3 \times regime_i + \epsilon_i\]
m3 <- lm(poids ~ taille + sport + regime)
summary(m3)
##
## Call:
## lm(formula = poids ~ taille + sport + regime)
##
## Residuals:
## Min 1Q Median 3Q Max
## -8.3520 -2.5752 -0.3603 2.3478 12.8767
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -70.15622 6.09121 -11.518 <2e-16 ***
## taille 0.84487 0.03491 24.204 <2e-16 ***
## sport -10.56913 0.84272 -12.542 <2e-16 ***
## regime 2.04703 0.82824 2.472 0.0152 *
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 3.459 on 96 degrees of freedom
## Multiple R-squared: 0.9296, Adjusted R-squared: 0.9274
## F-statistic: 422.4 on 3 and 96 DF, p-value: < 2.2e-16
Le coefficient associé au fait d’avoir suivi un régime amaigrissant durant les 12 derniers mois est estimé à la valeur 2,05 : autrement dit, en moyenne les personnes qui ont suivi un régime amaigrissant durant les 12 derniers moids pèsent 2,05 kg de plus que les autres.
Interrogées, les personnes déclarant avoir suivi un régime amaigrissant au cours des 12 derniers mois déclarent pourtant avoir perdu du poids, ce qui est confirmé par la comparaison des poids moyens au moment de l’enquête et un an avant (variable l.poids
) :
data.frame(
regime=c("Pas de régime amaigrissant","Régime amaigrissant")
, l.poids=as.numeric(by(l.poids,regime,mean))
, poids=as.numeric(by(poids,regime,mean))
, delta=as.numeric(by(poids,regime,mean)-by(l.poids,regime,mean))
)
## regime l.poids poids delta
## 1 Pas de régime amaigrissant 63.07692 63.43590 0.3589744
## 2 Régime amaigrissant 76.80328 75.34426 -1.4590164
Ce phénomène illustre le mécanisme de causalité inverse (cf. cours) : même si individuellement les personnes ayant suivi un régime amaigrissant ont perdu du poids, comme par ailleurs les personnes en surpoids ont une probabilité plus élevée de suivre de tels régimes, le coefficient estimé par la régression est globalement positif.
C’est ce type de situation qui justifie l’expression “corrélation n’est pas causalité” : le modèle de régression ne révèle que des associations statistiques, et non des relations de cause à effet. Pour mesurer l’efficacite des régimes en s’affranchissant de ce type d’endogénéité, on peut par exemple utiliser des données de panel (observations répétées dans le temps).
En parallèle des éléments théoriques introduits par le cours, un exemple est suivi tout du long : l’analyse des déterminants du salaire à partir des données de l’enquête Emploi en continu (EEC) du quatrième trimestre 2012 (extraction au 1/20ème). Les fichiers dont sont extraites ces données ainsi que leur documentation sont librement téléchargeables sur le site de l’Insee.
Les différentes variables explicatives sont ajoutées progressivement au modèle : âge, sexe, niveau de diplôme atteint, temps partiel, secteur d’emploi (public ou privé). Elles permettent de revenir sur certains concepts fondamentaux vus en cours :
Note : Ce plan diffère de celui suivi pendant le cours. Les modèles de régression estimés avec SAS et qui figurent dans le support de cours ont été adaptés en conséquence.
Les données utilisées sont stockées au format RDS dans le fichier http://teaching.slmc.fr/mqs2/ee12t4.rds. Le format RDS est un format propre à R de stockage des données sous une forme compressée (taper ?readRDS
dans R pour en savoir plus).
# Lecture des données et assignation à l'objet e
e <- readRDS(gzcon(url("http://teaching.slmc.fr/mqs2/ee12t4.rds")))
# Passage en minuscule des noms de variables et affichage de la structure de l'objet e
colnames(e) <- tolower(colnames(e))
str(e)
## 'data.frame': 1783 obs. of 19 variables:
## $ ident : chr "G0C5B116" "G0C5B1I6" "G0D5GIX6" "G0D5OGWD" ...
## $ noi : int 1 1 2 1 2 1 1 2 4 1 ...
## $ extri1613: num 1416 1524 1594 1988 2522 ...
## $ sexe : int 1 1 2 1 2 1 1 2 1 1 ...
## $ age : int 64 43 50 24 30 30 51 51 16 82 ...
## $ cse : int 37 23 46 56 NA 54 48 68 NA NA ...
## $ acteu : int 1 1 1 1 3 1 1 1 3 3 ...
## $ stc : int 2 1 2 2 NA 2 2 2 NA NA ...
## $ tam1d : int NA 1 NA NA NA NA NA NA NA NA ...
## $ aidref : int NA NA NA NA 4 NA NA NA 5 NA ...
## $ salred : int 3350 NA 2508 1500 NA 1517 3163 950 NA NA ...
## $ tpp : int 1 1 1 1 NA 1 1 1 NA NA ...
## $ ddipl : int 4 1 3 4 5 1 5 7 6 7 ...
## $ nbagenf : int 0 1 0 0 0 0 1 1 1 0 ...
## $ duhab : int 7 7 7 6 NA 6 6 6 NA NA ...
## $ pub3fp : int 4 NA 4 4 NA 4 4 4 NA NA ...
## $ naia : int 1948 1969 1962 1988 1982 1982 1961 1961 1995 1930 ...
## $ fordat : int 1970 1992 1982 2007 2000 2006 1978 1977 NA NA ...
## $ ancentr : int 108 72 50 30 NA 5 372 132 NA NA ...
Passer le nom des variables des tables importées en minuscule n’est absolument pas obligatoire, mais cela permet de faire moins d’erreurs par la suite.
La variable dépendante de l’étude, salred
, est le salaire mensuel en euros redressé : certains enquêtés préfèrent en effet déclarer leur salaire en tranches, voire refusent de le déclarer. Des techniques plus ou moins complexes sont utilisées pour imputer une valeur à l’ensemble des salariés.
# Distribution de salred
summary(e$salred)
## Min. 1st Qu. Median Mean 3rd Qu. Max. NA's
## 31 1250 1600 1851 2168 11420 1004
# On supprime les 1 004 observations pour lesquelles salred est manquant (inactifs, chômeurs, indépendants, etc.)
e <- e[!is.na(e$salred),]
nrow(e)
## [1] 779
On commence par estimer un modèle de régression linéaire simple de la forme : \[\text{(m1)} \quad salaire_i = \beta_0 + \beta_1 \times age_i + \epsilon_i\] en utilisant la fonction lm()
:
# Estimation du modèle m1
m1 <- lm(salred ~ age, data = e)
# Résumé du modèle m1
summary(m1)
##
## Call:
## lm(formula = salred ~ age, data = e)
##
## Residuals:
## Min 1Q Median 3Q Max
## -2123.9 -603.6 -166.3 315.2 9864.3
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 904.887 160.700 5.631 2.51e-08 ***
## age 22.544 3.697 6.099 1.68e-09 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 1168 on 777 degrees of freedom
## Multiple R-squared: 0.04568, Adjusted R-squared: 0.04445
## F-statistic: 37.19 on 1 and 777 DF, p-value: 1.684e-09
Âge et salaire semblent ainsi positivement corrélés : une augmentation de l’âge de 1 an dans l’échantillon est associée en moyenne à une augmentation de salaire de 22,5 euros par mois. Sa p-valeur étant inférieure à 0,01, ce coefficient est significatif au seuil de 1 % (cf. cours). Graphiquement, il est possible de représenter la prédiction du modèle par une droite :
# Construction du nuage de point
plot(e$age,e$salred,xlab="Âge en années",ylab="Salaire en euros")
# Ajout d'une droite d'équation y = coef(m1)[1] + coef(m1)[2] * x
abline(a = coef(m1)[1], b = coef(m1)[2])
# Ajout d'un titre général
title(main="Représentation graphique de la prédiction du modèle m1")
Certaines valeurs extrêmes de salaire polarisent très fortement le nuage de points. Pour limiter cet effet, on peut modifier la spécification du modèle en régressant le salaire en logarithme : \[\text{(m2)} \quad \ln(salaire_i) = \beta_0 + \beta_1 \times age_i + \epsilon_i\]
# Création de la variable lnsalred
e$lnsalred <- log(e$salred)
# Estimation du modèle m2
m2 <- lm(lnsalred ~ age, data = e)
# Affichage des coefficients du modèle m2
summary(m2)$coefficients
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 6.84842934 0.086897843 78.810119 0.000000e+00
## age 0.01186784 0.001998874 5.937264 4.367229e-09
Le coefficient de l’âge s’interprète désormais comme l’augmentation de salaire moyenne en pourcentage associé à 1 an supplémentaire dans l’échantillon, ici + 1,19 %.
Il est également fréquent d’introduire certaines variables explicatives avec leur carré (tout particulièrement dans le cas de l’âge), ce qui permet de capter certaines relations non-linéaires. On estime alors le modèle : \[\text{(m3)} \quad \ln(salaire_i) = \beta_0 + \beta_1 \times age_i + \beta_2 \times age_i^2 + \epsilon_i\]
# Création de la variable d'âge au carré age2
e$age2 <- e$age^2
# Estimation du modèle m3
m3 <- lm(lnsalred ~ age + age2, data = e)
# Affichage des coefficients du modèle m3
summary(m3)$coefficients
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 5.4874355803 0.2605441145 21.061445 3.102072e-78
## age 0.0839229496 0.0131807866 6.367067 3.296151e-10
## age2 -0.0008801731 0.0001592134 -5.528259 4.419753e-08
\(\beta_1\) et \(\beta_2\) doivent alors être interprétés conjointement (cf. cours). Graphiquement, la prédiction du modèle m3 peut être représentée par une courbe :
# Construction du nuage de points
plot(e$age,e$lnsalred,xlab="Âge en années",ylab="Logarithme du salaire")
# Ajout de la courbe représentant la prédiction du modèle m3
curve(coef(m3)[1] + coef(m3)[2]*x + coef(m3)[3]*x^2, add=TRUE)
# Ajout d'un titre général
title(main="Représentation graphique de la prédiction du modèle m3")
De nombreux travaux d’économie et de sociologie du travail montrent l’existence d’un phénomène de discrimination salariale : à caractéristiques égales, être une femme est associé à un salaire en moyenne plus faible. La méthode de la régression linéaire multiple permet précisément de mettre en évidence le lien entre sexe et salaire en contrôlant par l’ensemble des autres variables disponibles dans les données.
Pour introduire la variable sexe
dans la régression, on commence par la dichotomiser : on crée la variable homme
valant 1
si l’individu est un homme et 0
sinon et la variable femme
valant 1
si l’individu est une femme et 0
sinon. Ces variables permettent tout d’abord d’indiquer le sexe des individus sur le nuage de points du logarithme du salaire en fonction de l’âge :
# Dichotomisation de la variable codant le sexe
e$homme <- (e$sexe == 1) * 1
e$femme <- (e$sexe == 2) * 1
# Construction du nuage de points en distinguant les hommes et les femmes
plot(e$age,e$lnsalred,pch = e$femme,xlab="Âge en années",ylab="Logarithme du salaire")
# Ajout d'une légende
legend("topleft",legend=c("Hommes","Femmes"),pch=c(0,1))
# Ajout d'un titre général
title(main="Logarithme du salaire, âge et sexe")
Il semble qu’il y ait davantage de femmes dans les valeurs extrêmes faibles et d’hommes dans les valeurs extrêmes élevées. Pour confirmer cette impression, on estime le modèle m4
: \[\text{(m4)} \quad \ln(salaire_i) = \beta_0 + \beta_1 age_i + \beta_2 age_i^2 + \beta_3 femme_i + \beta_4 homme_i + \epsilon_i\]
# Estimation du modèle m4
m4 <- lm(lnsalred ~ age + age2 + femme + homme, data = e)
# Affichage des coefficients du modèle m4
summary(m4)
##
## Call:
## lm(formula = lnsalred ~ age + age2 + femme + homme, data = e)
##
## Residuals:
## Min 1Q Median 3Q Max
## -3.2079 -0.2628 0.0385 0.3483 1.9731
##
## Coefficients: (1 not defined because of singularities)
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 5.7038824 0.2501340 22.803 < 2e-16 ***
## age 0.0828141 0.0125918 6.577 8.83e-11 ***
## age2 -0.0008742 0.0001521 -5.748 1.30e-08 ***
## femme -0.3686416 0.0424589 -8.682 < 2e-16 ***
## homme NA NA NA NA
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.592 on 775 degrees of freedom
## Multiple R-squared: 0.1612, Adjusted R-squared: 0.158
## F-statistic: 49.66 on 3 and 775 DF, p-value: < 2.2e-16
La ligne correspondant à la variable homme
ne comporte que des NA
(pour Not Assigned). R a en effet automatiquement exclu cette variable du modèle en raison du phénomène de colinéarité (cf. cours). De manière générale, pour introduire une variable qualitative il convient de la dichotomiser et d’introduire toutes les variables indicatrices sauf une (cf. infra avec le diplôme sur le choix de cette modalité). Le modèle m4
estimé est donc en fait : \[\text{(m4)} \quad \ln(salaire_i) = \beta_0 + \beta_1 age_i + \beta_2 age_i^2 + \beta_3 femme_i + \epsilon_i\]
# Ré-estimation du modèle m4 (sans la colinéarité)
m4 <- lm(lnsalred ~ age + age2 + femme, data = e)
# Affichage des coefficients du modèle m4
summary(m4)$coefficients
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 5.7038824061 0.2501339896 22.803308 1.801019e-88
## age 0.0828140895 0.0125917871 6.576834 8.834572e-11
## age2 -0.0008741721 0.0001520925 -5.747633 1.301026e-08
## femme -0.3686415575 0.0424589295 -8.682309 2.273092e-17
Dans le cas des variables dichotomiques comme le sexe, l’interprétation du coefficient est simple : celui-ci correspond à l’écart moyen associé au fait d’avoir la caractéristique codée par la variable dichotomique. Dans le cas du modèle m4
, le fait d’être une femme est associé, à âge égal, à un salaire en moyenne de 36,9 % inférieur. La prédiction de ce modèle peut être représentée par deux courbes :
# Construction du nuage de points
plot(e$age,e$lnsalred,pch = e$femme,xlab="Âge en années",ylab="Logarithme du salaire")
# Ajout des courbes représentant la prédiction du modèle m4
curve(coef(m4)[1] + coef(m4)[2]*x + coef(m4)[3]*x^2, add=TRUE)
curve(coef(m4)[1] + coef(m4)[4] + coef(m4)[2]*x + coef(m4)[3]*x^2, lty=2, add=TRUE)
# Ajout d'une légende mixte
legend("topleft",legend=c("Hommes","Femmes"),pch=c(0,1),lty=c(1,2))
# Ajout d'un titre général
title(main="Représentation graphique de la prédiction du modèle m4")
Pour approfondir la question de la discrimination salariale, on peut chercher à neutraliser l’effet du diplôme sur le salaire. Pour ce faire, il suffit de rajouter les modalités de la variable ddipl
dans le modèle de régression (sauf la dernière) : \[\text{(m5)} \quad \ln(salaire_i) = \beta_0 + \beta_1 age_i + \beta_2 age_i^2 + \beta_3 femme_i + \beta_4 ddipl1_i + \beta_5 ddipl3_i + ... + \beta_8 ddipl6_i +\epsilon_i\]
# Dichotomisation de la variable de niveau de diplôme
e$ddipl1 <- (e$ddipl == 1) * 1 # Diplôme supérieur à baccalauréat + 2 ans
e$ddipl3 <- (e$ddipl == 3) * 1 # Baccalauréat + 2 ans
e$ddipl4 <- (e$ddipl == 4) * 1 # Baccalauréat ou brevet professionnel ou autre diplôme de ce niveau
e$ddipl5 <- (e$ddipl == 5) * 1 # CAP, BEP ou autre diplôme de ce niveau
e$ddipl6 <- (e$ddipl == 6) * 1 # Brevet des collèges
e$ddipl7 <- (e$ddipl == 7) * 1 # Aucun diplôme ou certificat d'études primaires
# Estimation du modèle m5
m5 <- lm(lnsalred ~ age + age2 + femme + ddipl1 + ddipl3 + ddipl4 + ddipl5 + ddipl6, data = e)
# Résumé du modèle m5
summary(m5)
##
## Call:
## lm(formula = lnsalred ~ age + age2 + femme + ddipl1 + ddipl3 +
## ddipl4 + ddipl5 + ddipl6, data = e)
##
## Residuals:
## Min 1Q Median 3Q Max
## -3.2307 -0.2146 0.0671 0.2927 1.9488
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 5.4264080 0.2330520 23.284 < 2e-16 ***
## age 0.0691972 0.0116498 5.940 4.32e-09 ***
## age2 -0.0006555 0.0001412 -4.641 4.07e-06 ***
## femme -0.3961442 0.0391407 -10.121 < 2e-16 ***
## ddipl1 0.7714419 0.0699169 11.034 < 2e-16 ***
## ddipl3 0.6990360 0.0730079 9.575 < 2e-16 ***
## ddipl4 0.5127076 0.0667608 7.680 4.84e-14 ***
## ddipl5 0.3052744 0.0644052 4.740 2.55e-06 ***
## ddipl6 0.3301545 0.0994454 3.320 0.000943 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.54 on 770 degrees of freedom
## Multiple R-squared: 0.3067, Adjusted R-squared: 0.2995
## F-statistic: 42.58 on 8 and 770 DF, p-value: < 2.2e-16
Avant toute chose, on constate que même en intégrant le niveau de diplôme le coefficient associé au fait d’être une femme reste significatif et du même ordre de grandeur que dans le modèle précédent (en moyenne un salaire inférieur de 39,6 %)
Dans le cas d’une variable catégorielle à plusieurs modalités, les coefficients s’interprètent relativement à la modalité de différence. Ainsi dans le modèle m6
, le fait d’avoir le brevet des collèges (ddipl6
) par rapport à aucun diplôme ou le certificat d’étude primaire (ddipl7
, la référence) est associé, à sexe et âge égaux, à un salaire en moyenne 33,0 % supérieur.
Le choix de la modalité de référence est donc crucial pourl’interprétation des résultats, dans la mesure où il affecte la valeur des coefficients ainsi que les tests de significativité (cf. cours). Les modèles m6b
à m6f
sont des variantes du modèle m6
où la modalité de référence pour le diplôme est modifiée :
# Estimation des modèles m5b à m5f
m5b <- lm(lnsalred ~ age + age2 + femme + ddipl1 + ddipl3 + ddipl4 + ddipl5 + ddipl7, data = e)
m5c <- lm(lnsalred ~ age + age2 + femme + ddipl1 + ddipl3 + ddipl4 + ddipl6 + ddipl7, data = e)
m5d <- lm(lnsalred ~ age + age2 + femme + ddipl1 + ddipl3 + ddipl5 + ddipl6 + ddipl7, data = e)
m5e <- lm(lnsalred ~ age + age2 + femme + ddipl1 + ddipl4 + ddipl5 + ddipl6 + ddipl7, data = e)
m5f <- lm(lnsalred ~ age + age2 + femme + ddipl3 + ddipl4 + ddipl5 + ddipl6 + ddipl7, data = e)
# Affichage des coefficients des modèles m5b, m5d et m5f
summary(m5b)$coefficients
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 5.756562484 0.2392113212 24.064758 7.444386e-96
## age 0.069197201 0.0116497884 5.939782 4.319187e-09
## age2 -0.000655489 0.0001412384 -4.641012 4.074485e-06
## femme -0.396144237 0.0391406976 -10.121032 1.086937e-22
## ddipl1 0.441287341 0.0979900521 4.503389 7.723714e-06
## ddipl3 0.368881430 0.1001984990 3.681507 2.480444e-04
## ddipl4 0.182553033 0.0955541404 1.910467 5.644427e-02
## ddipl5 -0.024880171 0.0942519921 -0.263975 7.918698e-01
## ddipl7 -0.330154527 0.0994454102 -3.319957 9.426885e-04
summary(m5d)$coefficients
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 5.939115517 0.2305332000 25.762517 4.861661e-106
## age 0.069197201 0.0116497884 5.939782 4.319187e-09
## age2 -0.000655489 0.0001412384 -4.641012 4.074485e-06
## femme -0.396144237 0.0391406976 -10.121032 1.086937e-22
## ddipl1 0.258734308 0.0621396268 4.163757 3.484282e-05
## ddipl3 0.186328398 0.0652342668 2.856296 4.401572e-03
## ddipl5 -0.207433204 0.0568835020 -3.646632 2.835791e-04
## ddipl6 -0.182553033 0.0955541404 -1.910467 5.644427e-02
## ddipl7 -0.512707559 0.0667607629 -7.679774 4.842889e-14
summary(m5f)$coefficients
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 6.197849825 0.2360574201 26.255687 5.212520e-109
## age 0.069197201 0.0116497884 5.939782 4.319187e-09
## age2 -0.000655489 0.0001412384 -4.641012 4.074485e-06
## femme -0.396144237 0.0391406976 -10.121032 1.086937e-22
## ddipl3 -0.072405911 0.0681599288 -1.062294 2.884351e-01
## ddipl4 -0.258734308 0.0621396268 -4.163757 3.484282e-05
## ddipl5 -0.466167512 0.0598961190 -7.782934 2.282870e-14
## ddipl6 -0.441287341 0.0979900521 -4.503389 7.723714e-06
## ddipl7 -0.771441868 0.0699169027 -11.033696 2.209062e-26
La valeur (et notamment le signe) des paramètres estimés relatifs au diplôme change du tout au tout selon la modalité de référence choisie, de même pour les tests de significativité : en règle générale, quand la variable est ordonnée on préfère choisir comme modalité de référence une modalité plutôt centrale (cf. cours).
Un modèle de régression est d’autant meilleur qu’il parvient à minimiser la somme des carrés des résidus \(\sum_{i=1}^n \epsilon_i\). Le R2 est un indicateur construit sur ce principe, qui permet de rendre compte de la qualité de la prédiction produite par le modèle.
Cependant, quand on ajoute des variables explicatives mécaniquement le R2 augmente : le R2 ajusté permet de prendre en compte ce phénomène en privilégiant, à qualité de prédiction égale, les modèles les plus parcimonieux en variables explicatives.
La fonction summary()
affiche par défaut la valeur du R2, du R2 ajusté. Pour comparer ces statistiques dans les 10 premiers modèles, on les centralise dans un tableau en utilisant la fonction sapply()
(?sapply
pour plus de détails).
liste <- list(m1,m2,m3,m4,m5,m5b,m5c,m5d,m5e,m5f)
data.frame(
modele=c("m1","m2","m3","m4","m5","m5b","m5c","m5d","m5e","m5f")
, R2=sapply(liste,function(x){summary(x)$r.square})
, R2adj=sapply(liste,function(x){summary(x)$adj.r.square})
)
## modele R2 R2adj
## 1 m1 0.04568262 0.04445442
## 2 m2 0.04339927 0.04216812
## 3 m3 0.07964610 0.07727405
## 4 m4 0.16123123 0.15798439
## 5 m5 0.30670561 0.29950255
## 6 m5b 0.30670561 0.29950255
## 7 m5c 0.30670561 0.29950255
## 8 m5d 0.30670561 0.29950255
## 9 m5e 0.30670561 0.29950255
## 10 m5f 0.30670561 0.29950255
Par construction, le R2 ajusté est toujours inférieur au R2 (mais d’assez peu ici car il y a peu de variables), et au fur et à mesure qu’on ajoute des variables explicatives, les deux statistiques augmentent. Avec les variables d’âge, de sexe et de niveau de diplôme, le modèle parvient à expliquer 30 % de la variance du salaire en logarithme, ce qui est acceptable étant donnée sa parcimonie. Au passage, on observe qu’un changement dans la modalité de référence n’induit aucun changement dans la qualité de prédiction globale du modèle, d’où les valeurs identiques pour les modèles m5
à m5f
.
R2 et R2 ajusté constituent de bons indicateurs du pouvoir prédictif d’un modèle (sur les différentes finalités de la modélisation économétrique, cf. la conclusion de la séance 1). Pour juger de leur pouvoir explicatif, il est possible de tester conjointement la significativité de toutes les variables introduites dans le modèle. Si l’on peut rejeter à un seuil raisonnable l’hypothèse qu’aucune des variables n’est significative, alors cela signifie que le modèle présente un certain pouvoir explicatif.
Dès le modèle m1
, la p-valeur du test de Fisher est inférieure à 0,001 : avec la seule variable d’âge l’association avec la variable de salaire est suffisante pour qu’on puisse estimer avec un risque très faible de se tromper (très inférieur à 0, %) que le modèle apporte des éléments d’explication de la ditribution des salaires.
Les deux autres variables que l’on souhaite intégrer dans le modèle sont le fait de travailler à temps partiel et le secteur d’emploi (public ou privé).
On estime tout d’abord le modèle m6
(en reprenant toutes les variables du modèle m5d
) : \[ \text{(m6)} \quad \ln(salaire_i) = \beta_0 + \beta_1 age_i ... + \beta_8 ddipl7_i + \beta_9 tpp_i +\epsilon_i\]
# Recodage de tpp sous forme d'indicatrice
e$tpp <- (e$tpp == 2) * 1
# Estimation du modèle m6
m6 <- lm(lnsalred ~ age + age2 + femme + ddipl1 + ddipl3 + ddipl5 + ddipl6 + ddipl7 + tpp, data = e)
# Résumé du modèle m6
summary(m6)
##
## Call:
## lm(formula = lnsalred ~ age + age2 + femme + ddipl1 + ddipl3 +
## ddipl5 + ddipl6 + ddipl7 + tpp, data = e)
##
## Residuals:
## Min 1Q Median 3Q Max
## -2.71034 -0.21731 0.01168 0.24895 1.91424
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 6.0577416 0.2002346 30.253 < 2e-16 ***
## age 0.0641887 0.0101166 6.345 3.80e-10 ***
## age2 -0.0005827 0.0001227 -4.750 2.43e-06 ***
## femme -0.2300553 0.0355410 -6.473 1.71e-10 ***
## ddipl1 0.2717526 0.0539415 5.038 5.87e-07 ***
## ddipl3 0.1348533 0.0567137 2.378 0.0177 *
## ddipl5 -0.2059405 0.0493732 -4.171 3.38e-05 ***
## ddipl6 -0.1351951 0.0829914 -1.629 0.1037
## ddipl7 -0.4712866 0.0580047 -8.125 1.78e-15 ***
## tpp -0.7340425 0.0461421 -15.908 < 2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.4687 on 769 degrees of freedom
## Multiple R-squared: 0.4784, Adjusted R-squared: 0.4723
## F-statistic: 78.36 on 9 and 769 DF, p-value: < 2.2e-16
Le R2 de la régression augmente très fortement (à 0,4784
), ce qui indique que la variable de temps partiel est déterminante pour comprendre les écarts de salaire dans notre échantillon (ce qui est assez logique). L’amplitude de l’écart de salaire entre hommes et femmes est plus faible que précédemment (-23,0 %) : cela est dû au fait que les femmes travaillent bien plus souvent à temps partiel que les hommes (29,0 % contre 7,1 %), et que le temps partiel est associé à un salaire en moyenne beaucoup plus faible (1 006 euros contre 2 035 euros pour un temps complet). Il s’agit d’un effet de structure.
# Temps partiel selon le sexe
data.frame(
sexe=c("Homme","Femme")
,tpp=as.numeric(by(e$tpp,e$femme,mean))
)
## sexe tpp
## 1 Homme 0.07070707
## 2 Femme 0.28981723
# Salaire et temps partiel
data.frame(
tpp=c("Temps complet","Temps partiel")
,salred=as.numeric(by(e$salred,e$tpp,mean))
)
## tpp salred
## 1 Temps complet 2034.777
## 2 Temps partiel 1005.727
On peut formuler l’hypothèse que les écarts de salaire entre hommes et femmes sont plus faibles dans le secteur public que dans le secteur privé, dans la mesure où l’évolution salariale y est fortement déterminée par des grilles communes.
On peut commencer par estimer le modèle : \[ \text{(m7)} \quad \ln(salaire_i) = \beta_0 + \beta_1 age_i ... + \beta_9 tpp_i + \beta_{10} public_i +\epsilon_i\]
# Création de la variable public à partir de pub3fp
e$public <- (e$pub3fp %in% c('1','2','3')) * 1
# Estimation du modèle m7
m7 <- lm(lnsalred ~ age + age2 + femme + ddipl1 + ddipl3 + ddipl5 + ddipl6 + ddipl7 + tpp + public, data = e)
# Résumé du modèle m7
summary(m7)
##
## Call:
## lm(formula = lnsalred ~ age + age2 + femme + ddipl1 + ddipl3 +
## ddipl5 + ddipl6 + ddipl7 + tpp + public, data = e)
##
## Residuals:
## Min 1Q Median 3Q Max
## -2.69361 -0.21361 0.01218 0.24854 1.92101
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 6.0492156 0.2003470 30.194 < 2e-16 ***
## age 0.0643376 0.0101158 6.360 3.46e-10 ***
## age2 -0.0005858 0.0001227 -4.775 2.16e-06 ***
## femme -0.2368066 0.0360443 -6.570 9.28e-11 ***
## ddipl1 0.2670390 0.0540971 4.936 9.77e-07 ***
## ddipl3 0.1345860 0.0567050 2.373 0.0179 *
## ddipl5 -0.2020448 0.0494879 -4.083 4.92e-05 ***
## ddipl6 -0.1284620 0.0831960 -1.544 0.1230
## ddipl7 -0.4632515 0.0584387 -7.927 7.89e-15 ***
## tpp -0.7372579 0.0462241 -15.950 < 2e-16 ***
## public 0.0476773 0.0426322 1.118 0.2638
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.4686 on 768 degrees of freedom
## Multiple R-squared: 0.4792, Adjusted R-squared: 0.4724
## F-statistic: 70.67 on 10 and 768 DF, p-value: < 2.2e-16
Le coefficient associé à la variable public
est faible et non significatif. Cependant, l’interprétation de ce seul coefficient ne permet pas d’apporter une réponse à notre hypothèse : il rend en effet compte de l’association moyenne entre secteur et salaire, sans qu’il soit possible que cette association diffère entre hommes et femmes. En d’autres termes, pour répondre à la question posée on souhaiterait croiser les variables sexe et secteur en estimant le modèle : \[ \text{(m8)} \quad \ln(salaire_i) = \beta_0 + \beta_1 age_i ... + \beta_8 tpp_i + \beta_9 femme\_prive_i + \beta_{10} homme\_public_i + \beta_{11} femme\_public _i +\epsilon_i\]
# Création des variables croisées
e$homme_prive <- e$homme*(1-e$public)
e$femme_prive <- e$femme*(1-e$public)
e$homme_public <- e$homme*e$public
e$femme_public <- e$femme*e$public
# Estimation du modèle m8
m8 <- lm(lnsalred ~ age + age2 + ddipl1 + ddipl3 + ddipl5 + ddipl6 + ddipl7 + tpp + femme_prive + homme_public + femme_public, data = e)
# Résumé du modèle m8
summary(m8)
##
## Call:
## lm(formula = lnsalred ~ age + age2 + ddipl1 + ddipl3 + ddipl5 +
## ddipl6 + ddipl7 + tpp + femme_prive + homme_public + femme_public,
## data = e)
##
## Residuals:
## Min 1Q Median 3Q Max
## -2.65817 -0.21630 0.02006 0.25250 1.90068
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 6.0549018 0.1992901 30.382 < 2e-16 ***
## age 0.0648655 0.0100635 6.446 2.03e-10 ***
## age2 -0.0005866 0.0001220 -4.807 1.85e-06 ***
## ddipl1 0.2712860 0.0538275 5.040 5.81e-07 ***
## ddipl3 0.1342370 0.0564034 2.380 0.01756 *
## ddipl5 -0.2097652 0.0492902 -4.256 2.34e-05 ***
## ddipl6 -0.1356673 0.0827874 -1.639 0.10168
## ddipl7 -0.4736262 0.0582279 -8.134 1.67e-15 ***
## tpp -0.7373260 0.0459782 -16.036 < 2e-16 ***
## femme_prive -0.2881022 0.0396268 -7.270 8.85e-13 ***
## homme_public -0.1213313 0.0699339 -1.735 0.08315 .
## femme_public -0.1463200 0.0526571 -2.779 0.00559 **
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.4661 on 767 degrees of freedom
## Multiple R-squared: 0.4854, Adjusted R-squared: 0.478
## F-statistic: 65.77 on 11 and 767 DF, p-value: < 2.2e-16
Pour les salariés du privé, à âge et diplôme égaux et en contrôlant par le fait d’être à temps partiel ou non, le fait d’être une femme est associé à un salaire moyen inférieur de 28,8 %. Dans le secteur public, cet écart est de l’ordre de 2,5 %.
Quand des variables croisées interviennent dans un modèle, il est pertinent de mener d’autres tests que le seul test de significativité :
Pour mener à bien ces tests d’hypothèse, il suffit de modifier la modalité de référence (modèles m8b
et m8c
).
# Estimation du modèle m8b avec femme_prive comme référence (pour tester l'écart avec femme_public)
m8b <- lm(lnsalred ~ age + age2 + ddipl1 + ddipl3 + ddipl5 + ddipl6 + ddipl7 + tpp + homme_prive + homme_public + femme_public, data = e)
# Affichage des coefficients pertinents du modèle m8b
summary(m8b)$coefficients[10:12,]
## Estimate Std. Error t value Pr(>|t|)
## homme_prive 0.2881022 0.03962682 7.270384 8.851702e-13
## homme_public 0.1667709 0.07136585 2.336845 1.970377e-02
## femme_public 0.1417821 0.05250716 2.700244 7.081603e-03
Toutes les autres variables du modèle contrôlées par ailleurs, en moyenne le salaire des femmes dans le secteur public est supérieur de 14,2 % à celui des femmes dans le secteur privé (femme_prive
est la référence dans le modèle m8b
). La p-valeur du test de significativité de femme_public
étant inférieure à 0.01 (égale à 0,007), cet écart est significatif au seuil de 1 %.
# Estimation du modèle m8c avec homme_public comme référence (pour tester l'écart avec femme_public)
m8c <- lm(lnsalred ~ age + age2 + ddipl1 + ddipl3 + ddipl5 + ddipl6 + ddipl7 + tpp + homme_prive + femme_prive + femme_public, data = e)
# Affichage des coefficients pertinents du modèle m8c
summary(m8c)$coefficients[10:12,]
## Estimate Std. Error t value Pr(>|t|)
## homme_prive 0.12133127 0.06993388 1.7349428 0.08315264
## femme_prive -0.16677090 0.07136585 -2.3368447 0.01970377
## femme_public -0.02498877 0.07837733 -0.3188266 0.74994484
Dans le modèle 8c
où homme_public
est la modalité de référence, le coefficient associé à femme_public
n’est pas significativement différent de 0 (p-valeur de 0,750) : toutes les variables du modèle étant contrôlées par ailleurs, on ne peut pas distinguer d’écart de salaire significatif entre hommes et femmes dans le secteur public.
Croiser des variables explicatives dans un modèle permet souvent d’apporter des éléments de réponse à des hypothèses de travail très concrètes. Au-delà des seules variables qualitatives, il est également possible de croiser une variable qualitative et une variable quantitative. Afin de pouvoir représenter graphiquement l’impact du croisement de ces variables sur la modélisation, on repart du modèle m4
: \[\text{(m4)} \quad \ln(salaire_i) = \beta_0 + \beta_1 age_i + \beta_2 age_i^2 + \beta_3 femme_i + \epsilon_i\]
Pour croiser sexe et âge, il suffit d’autoriser les coefficients relatifs à l’âge à varier en fonction du sexe : \[\text{(m9)} \quad \ln(salaire_i) = \beta_0 + \beta_1 femme_i + homme_i \times (\beta_2 age_i + \beta_3 age_i^2) + femme_i \times (\beta_4 age_i + \beta_5 age_i^2) + \epsilon_i\]
En pratique, on définit la variable age_homme
qui vaut l’âge pour les hommes et 0 pour les femmes et la variable age_femme
qui faut l’âge pour les femmes et 0 pour les hommes, ainsi que leur carré respectif (age2_homme
et age2_femme
).
# Construction des variables de croisement
e$age_homme <- e$age*e$homme
e$age_femme <- e$age*e$femme
e$age2_homme <- e$age_homme^2
e$age2_femme <- e$age_femme^2
# Estimation du modèle m9
m9 <- lm(lnsalred ~ femme + age_homme + age2_homme + age_femme + age2_femme, data = e)
# Résumé du modèle m9
summary(m9)
##
## Call:
## lm(formula = lnsalred ~ femme + age_homme + age2_homme + age_femme +
## age2_femme, data = e)
##
## Residuals:
## Min 1Q Median 3Q Max
## -3.3030 -0.2592 0.0454 0.3369 2.0352
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 5.5364945 0.3454229 16.028 < 2e-16 ***
## femme -0.0368156 0.4967968 -0.074 0.941
## age_homme 0.0858810 0.0174282 4.928 1.02e-06 ***
## age2_homme -0.0008548 0.0002105 -4.061 5.38e-05 ***
## age_femme 0.0797460 0.0181087 4.404 1.21e-05 ***
## age2_femme -0.0008941 0.0002188 -4.087 4.83e-05 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.5904 on 773 degrees of freedom
## Multiple R-squared: 0.168, Adjusted R-squared: 0.1626
## F-statistic: 31.21 on 5 and 773 DF, p-value: < 2.2e-16
On voit que les coefficients de age_homme
et age_femme
diffèrent sensiblement, avec age_homme > age_femme
: cela semble indiquer qu’en moyenne dans l’échantillon, le gain de salaire associé à 1 an d’âge supplémentaire est supérieur pour les hommes.
# Construction du nuage de points
plot(e$age,e$lnsalred,pch = e$femme,xlab="Âge en années",ylab="Logarithme du salaire")
# Ajout des courbes représentant la prédiction du modèle m9
curve(coef(m9)[1] + coef(m9)[3]*x + coef(m9)[4]*x^2, add=TRUE)
curve(coef(m9)[1] + coef(m9)[2] + coef(m9)[5]*x + coef(m9)[6]*x^2, lty=2, add=TRUE)
# Ajout d'une légende mixte
legend("topleft",legend=c("Hommes","Femmes"),pch=c(0,1),lty=c(1,2))
# Ajout d'un titre général
title(main="Représentation graphique de la prédiction du modèle m9")
Le croisement de l’âge et du sexe permet ainsi de mettre en évidence un écart de salaire entre hommes et femmes qui se creuse avec l’âge.
Il est également possible de mener à bien des tests d’hypothèsees complexes quand les variables croisées sont qualitatives et quantitatives. Dans l’exemple, cela revient à tester si les coefficients associés à l’âge sont significativement différents pour les hommes et les femmes. Une analyse de la variance permet de construire le test approprié : si le logarithme du salaire est bien mieux expliqué par le modèle m9
que par le modèle m4
, alors ces coefficients sont significativement différents les uns des autres.
# Analyse de la variance des modèles m4 et m9
anova(m4,m9)
## Analysis of Variance Table
##
## Model 1: lnsalred ~ age + age2 + femme
## Model 2: lnsalred ~ femme + age_homme + age2_homme + age_femme + age2_femme
## Res.Df RSS Df Sum of Sq F Pr(>F)
## 1 775 271.62
## 2 773 269.43 2 2.1871 3.1374 0.04395 *
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
La p-valeur du test de Fisher est de 0,044 < 0,050 : on peut donc rejeter l’hypothèse nulle d’égalité des coefficients \(\beta_2\) et \(\beta_4\) d’une part, \(\beta_3\) et \(\beta_5\) d’autre part (en reprenant les notations du modèle m9
).
Dans un article de 1995, l’économiste L.E. Papke propose une analyse empirique de l’adhésion des salariés américains à un certain type de programmes de retraite d’entreprise (programmes 401(k)) en fonction de la générosité de l’employeur (au sens de la part que représente sa contribution au programme). Le fichier http://teaching.slmc.fr/mqs2/401k.dta comporte une partie de l’échantillon d’entreprises utilisé dans cette étude ; il est décrit par le fichier http://teaching.slmc.fr/mqs2/401k.des. En particulier:
prate
est le pourcentage de salariés de l’entreprise adhérant à un programme de retraite 401(k)mrate
est la part que représente l’abondement de l’employeur. Si mrate = 0.50
, alors pour 1 dollar épargné l’employeur abonde à hauteur de 50 cents.L’objectif de cet exercice, repris de l’ouvrage de J.M. Wooldridge cité en bibliographie (cf. introduction du cours), est d’étudier la relation entre prate
et mrate
.
library()
pour charger le package foreign
. Utilisez sa fonction read.dta()
pour charger les données du fichier http://teaching.slmc.fr/mqs2/401k.dta dans R. Affichez la structure des données importées (nombre de variables, d’observations, etc.)
lm()
pour estimer le modèle \[\text{(m1)} \quad prate = \beta_0 + \beta_1mrate + \epsilon\] Interprétez la valeur des estimations des coefficients \(\beta_0\) et \(\beta_1\).
prate
et mrate
par un nuage de points ainsi que la prédiction du modèle m1
(pensez à vous inspirer des graphiques produits lors de la séance 1).
# Lecture des données et assignation à l'objet e
e <- readRDS(gzcon(url("http://teaching.slmc.fr/mqs2/ee12t4_new.rds")))
# Passage en minuscule des noms de variables et recodage de la variable d'âge
colnames(e) <- tolower(colnames(e))
e$age <- as.numeric(e$age)
# Création d'une variable de stabilité du contrat de travail
# et restriction de l'échantillon aux individus pour lesquels
# elle est pertinente
e$stable[e$chpub == "1" & e$titc %in% c("1","2")] <- 1
e$stable[e$contra == "1"] <- 1
e$stable[e$contra %in% as.character(2:5)] <- 0
e <- e[!is.na(e$stable),]
# Définition de la fonction logit()
logit <- function(x) exp(x)/(1 + exp(x))
# Représentation de la relation entre âge et stabilité du contrat
plot(e$age,e$stable,xlab = "Âge en années", ylab =
"Contrat de travail stable ou non")
title(main = "Relation entre âge et stabilité du contrat")
# Installation, chargement et utilisation du package data.table pour agréger les informations efficacement
# install.packages("data.table")
library(data.table)
ag <-data.table(e)[,j=list(count=.N),by=list(stable,age)]
# Représentation de la relation entre âge et travail
plot(e$age,e$stable,type="n",xlab = "Âge en années", ylab =
"Contrat de travail stable ou non")
symbols(x=ag$age, y=ag$stable, circles=ag$count, inches=1/4, ann=F, bg="cornflowerblue", fg=NULL, add = T)
title(main = "Relation entre âge et stabilité du contrat")
# Représentation de la relation entre âge et travail (troisième essai)
plot(e$age,e$stable,type="n",xlab = "Âge en années", ylab =
"Contrat de travail stable ou non")
symbols(x=ag$age, y=ag$stable, circles=sqrt(ag$count), inches=1/4, ann=F, bg="cornflowerblue", fg=NULL, add = T)
# Sauvegarde du graph pour la suite (sans son titre)
g1 <- recordPlot()
# Ajout du titre
title(main = "Relation entre âge et stabilité du contrat")
# Génération de données aléatoires
set.seed(1)
x <- rnorm(100,0,1)
x2 <- x^2
y <- 2*x + rnorm(100,0,1)
z <- ( exp(y)/(1+exp(y)) > 0.5 ) * 1
plot(x,z,pch=19,col="cornflowerblue")
# Estimation du modèle sim1 (linéaire) et représentation de sa prédiction
plot(x,z,pch=19,col="cornflowerblue")
sim1 <- glm(z ~ x,family=gaussian)
abline(a = coef(sim1)[1], b = coef(sim1)[2])
title(main = "Modèle linéaire appliqué à des données simulées")
# Estimation du modèle sim2 (linéaire général logit) et représentation de sa prédiction
plot(x,z,pch=19,col="cornflowerblue")
sim2 <- glm(z ~ x,family=binomial(link="logit"))
curve(logit(coef(sim2)[1] + coef(sim2)[2]*x), add=TRUE)
title(main = "Modèle logistique appliqué à des données simulées")
# Estimation du modèle sim3 (linéaire général probit) et représentation de sa prédiction
plot(x,z,pch=19,col="cornflowerblue")
sim3 <- glm(z ~ x,family=binomial(link="probit"))
curve(pnorm(coef(sim3)[1] + coef(sim3)[2]*x), add=TRUE)
title(main = "Modèle probit appliqué à des données simulées")
# Représentation des 3 modélisation sur le même graph
plot(x,z,pch=19,col="cornflowerblue")
abline(a = coef(sim1)[1], b = coef(sim1)[2],lty=1)
curve(logit(coef(sim2)[1] + coef(sim2)[2]*x), add=TRUE,lty=2)
curve(pnorm(coef(sim3)[1] + coef(sim3)[2]*x), add=TRUE,lty=3)
legend("right",c("Modèle linéaire","Modèle logit","Modèle probit"),lty=1:3)
title(main = "Comparaison des modèles sur données simulées")
# Estimation du modèle 1 (linéaire) et représentation de sa prédiction
m1 <- glm(stable~age,data=e,family=gaussian)
g1
abline(a = coef(m1)[1],b = coef(m1)[2],lty=1)
title(main = "Modèle linéaire simple appliqué aux données de l'EEC")
# Estimation du modèle 2 (linéaire général logit) et représentation de sa prédiction
m2 <- glm(stable ~ age,data=e,family=binomial(link="logit"))
g1
curve(logit(coef(m2)[1] + coef(m2)[2]*x), add=TRUE)
title(main = "Modèle logit simple appliqué aux données de l'EEC")
# Estimation du modèle 3 (linéaire général probit) et représentation de sa prédiction
m3 <- glm(stable ~ age,data=e,family=binomial(link="probit"))
g1
curve(pnorm(coef(m2)[1] + coef(m2)[2]*x), add=TRUE)
title(main = "Modèle probit simple appliqué aux données de l'EEC")
# Ajout d'une légende et d'un titre
g1
abline(a = coef(m1)[1],b = coef(m1)[2],lty=1)
curve(logit(coef(m2)[1] + coef(m2)[2]*x), add=TRUE,lty=2)
curve(pnorm(coef(m2)[1] + coef(m2)[2]*x), add=TRUE,lty=3)
legend("right",c("Modèle linéaire","Modèle logit","Modèle probit"),lty=1:3)
title(main = "Comparaison des modèles sur les données de l'EEC")
# Fonction logistique et fonction Phi
plot(x=1,type="n",xlim=c(-6,6),ylim=c(0,1),xlab="",ylab="")
curve(logit(x), add=TRUE,lty=2)
curve(pnorm(x), add=TRUE,lty=3)
legend("right",c("Fonction logit","Fonction Phi"),lty=2:3)
title(main = "Fonction logistique et fonction Phi")
# Option graphique pour avoir les deux graphiques côte-à-côte
# par(mfrow=c(1,2))
# Représentation de la prédiction d'une modélisation vraisemblable de z
col1 <- rep("cornflowerblue",100)
col1[c(59,6)] <- "red"
col1[c(84,95)] <- "green"
plot(x,z,pch=19,col=col1)
curve(logit(coef(sim2)[1] + coef(sim2)[2]*x), add=TRUE)
text(x = 0.6, y = 0.5, "logit(b0A + b1A*x)")
title(main="Modélisation vraisemblable de z")
# Représentation de la prédiction d'une modélisation peu vraisemblable de z
col2 <- rep("cornflowerblue",100)
col2[(x < -1 & z == 0) | (x > 1 & z == 1)] <- "red"
plot(x,z,pch=19,col=col2)
curve(logit(-1.3*x), add=TRUE)
text(x = 0.8, y = 0.5, "logit(b0B + b1B*x)")
title(main="Modélisation peu vraisemblable de z")
# Réinitialisation de l'option graphique pour avoir les deux graphiques côte-à-côte et ajout du titre
# par(mfrow=c(1,1))
# title(main="Modélisation vraisemblable (à gauche) et peu vraisemblable \n (à droite) de z")
# Construction des variables explicatives supplémentaires
e <- within(e[!is.na(e$ddipl),],{
ddipl1 <- (ddipl == "1") * 1
ddipl3 <- (ddipl == "3") * 1
ddipl4 <- (ddipl == "4") * 1
ddipl5 <- (ddipl == "5") * 1
ddipl6 <- (ddipl == "6") * 1
ddipl7 <- (ddipl == "7") * 1
femme <- (sexe == "2") * 1
age1530 <- (age >= 15 & age <= 30) * 1
age3150 <- (age >= 31 & age <= 50) * 1
age5165 <- (age >= 51 & age <= 65) * 1
agri <- (nafg4n == "ES") * 1
indus <- (nafg4n == "ET") * 1
cons <- (nafg4n == "EU") * 1
tert <- (nafg4n == "EV") * 1
})
# Estimation d'un modèle un peu plus complet
m4 <- glm(stable ~ age1530 + age5165 + femme + ddipl1 + ddipl3 + ddipl5 + ddipl6 + ddipl7 + agri + cons + tert,data=e,family= binomial(link="logit"))
# Affichage des informations sur le modèle m4
(t1a <- cbind(
Var=rownames(summary(m4)$coefficients)
,data.frame(summary(m4)$coefficients,row.names=NULL)
))
## Var Estimate Std..Error z.value Pr...z..
## 1 (Intercept) 2.67652698 0.2551488 10.4900633 9.596409e-26
## 2 age1530 -1.62082391 0.1522592 -10.6451633 1.836619e-26
## 3 age5165 0.40179432 0.1942094 2.0688712 3.855818e-02
## 4 femme -0.42142108 0.1428129 -2.9508605 3.168900e-03
## 5 ddipl1 0.66964571 0.2178210 3.0742943 2.110012e-03
## 6 ddipl3 0.72026357 0.2384301 3.0208581 2.520595e-03
## 7 ddipl5 0.35229052 0.1989732 1.7705428 7.663677e-02
## 8 ddipl6 0.07985644 0.2737797 0.2916814 7.705302e-01
## 9 ddipl7 -0.27566101 0.2138604 -1.2889761 1.974064e-01
## 10 agri -0.65268362 0.5409504 -1.2065499 2.276055e-01
## 11 cons -0.37960462 0.3232267 -1.1744221 2.402260e-01
## 12 tert -0.55170790 0.2159040 -2.5553395 1.060843e-02
# Calcul des odds-ratio
t1b <- t1a[,c("Var","Estimate")]
t1b$OR <- exp(t1b$Estimate)
t1b$low <- exp(t1b$Estimate - qnorm(0.975) * t1a$Std..Error)
t1b$high <- exp(t1b$Estimate + qnorm(0.975) * t1a$Std..Error)
t1b
## Var Estimate OR low high
## 1 (Intercept) 2.67652698 14.5345268 8.8149094 23.9653591
## 2 age1530 -1.62082391 0.1977357 0.1467175 0.2664946
## 3 age5165 0.40179432 1.4945039 1.0213761 2.1867968
## 4 femme -0.42142108 0.6561138 0.4959256 0.8680440
## 5 ddipl1 0.66964571 1.9535451 1.2747174 2.9938702
## 6 ddipl3 0.72026357 2.0549748 1.2878177 3.2791296
## 7 ddipl5 0.35229052 1.4223217 0.9630117 2.1007004
## 8 ddipl6 0.07985644 1.0831316 0.6333438 1.8523493
## 9 ddipl7 -0.27566101 0.7590702 0.4991644 1.1543042
## 10 agri -0.65268362 0.5206467 0.1803372 1.5031451
## 11 cons -0.37960462 0.6841318 0.3630853 1.2890534
## 12 tert -0.55170790 0.5759653 0.3772407 0.8793749
# Centralisation des statistiques construites à partir de la vraisemblance
(t2 <- data.frame(
modele=c(paste0("sim",1:3),paste0("m",1:4))
, source=c(rep("Simulations",3),rep("EEC",4))
, description=c("Lineaire simple","Logit simple","Probit simple","Lineaire simple","Logit simple","Probit simple","Logit multiple")
, logLik=sapply(list(sim1,sim2,sim3,m1,m2,m3,m4),logLik)
, aic=sapply(list(sim1,sim2,sim3,m1,m2,m3,m4),function(x){x$aic})
))
## modele source description logLik aic
## 1 sim1 Simulations Lineaire simple -39.68448 85.36896
## 2 sim2 Simulations Logit simple -35.26943 74.53886
## 3 sim3 Simulations Probit simple -35.20471 74.40942
## 4 m1 EEC Lineaire simple -660.80047 1327.60093
## 5 m2 EEC Logit simple -762.66522 1529.33044
## 6 m3 EEC Probit simple -768.51554 1541.03109
## 7 m4 EEC Logit multiple -744.08332 1512.16664
# Installation et chargement du package pROC (attention à la casse !)
# install.packages("pROC")
library(pROC)
## Type 'citation("pROC")' for a citation.
##
## Attaching package: 'pROC'
## The following objects are masked from 'package:stats':
##
## cov, smooth, var
# Courbe ROC sur les données simuleés
plot(roc(z ~ predict(sim2)),xlab="Spécificité : Part des négatifs classés négatifs",ylab="Sensibilité : Part des positifs classés positifs",main="Courbe ROC sur les données simulées")
##
## Call:
## roc.formula(formula = z ~ predict(sim2))
##
## Data: predict(sim2) in 41 controls (z 0) < 59 cases (z 1).
## Area under the curve: 0.9177
# Courbe ROC sur les données de l'EEC
plot(roc(e$stable ~ predict(m4)),xlab="Spécificité : Part des négatifs classés négatifs",ylab="Sensibilité : Part des positifs classés positifs",main="Courbe ROC sur les données de l'EEC")
##
## Call:
## roc.formula(formula = e$stable ~ predict(m4))
##
## Data: predict(m4) in 288 controls (e$stable 0) < 1818 cases (e$stable 1).
## Area under the curve: 0.7426
Cette séance aborde plusieurs questions communes aux modèles de régression sur données quantitatives et qualitatives :
# Génération de données aléatoires
n <- 500
set.seed(1)
age <- round(runif(n)*60+20,0)
prop <- F
prop[age < 30] <- (runif(sum(age<30)) < 0.10)
prop[age >= 30 & age < 50] <- (runif(sum(age >= 30 & age < 50)) < 0.50)
prop[age >= 50]<- (runif(sum(age >= 50)) < 0.70)
pat <- pmax(100*age + rnorm(n,10000,age*1000) + prop * rnorm(n,100000,age*6000),0)
# Représentation du patrimoine brut en fonction de l'âge
plot(age,pat,xlab = "Âge en années", ylab =
"Patrimoine brut")
title(main = "Patrimoine brut en fonction de l'âge")
# Estimation du modèle linéaire simple m1
m1 <- lm(pat ~ age)
summary(m1)
##
## Call:
## lm(formula = pat ~ age)
##
## Residuals:
## Min 1Q Median 3Q Max
## -170916 -105808 -61397 5536 1087919
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 2894.5 26209.1 0.110 0.912
## age 2100.3 498.5 4.214 2.98e-05 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 189400 on 498 degrees of freedom
## Multiple R-squared: 0.03442, Adjusted R-squared: 0.03248
## F-statistic: 17.75 on 1 and 498 DF, p-value: 2.985e-05
# Représentation de la prédiction du modèle m1
plot(age,pat,xlab = "Âge en années", ylab =
"Patrimoine brut")
abline(coef(m1)[1],coef(m1)[2])
title(main = "Prédiction du modèle m1")
# Représentation des résidus du modèle m1
plot(age,m1$residuals,xlab = "Âge en années", ylab =
"Résidus du modèle m1")
abline(0,0)
title(main = "Résidus du modèle m1")
sd(m1$residuals[age < 30])
## [1] 63013.76
sd(m1$residuals[age > 50])
## [1] 233291.5
# Estimation du modèle linéaire multiple m2
age2 <- age^2
m2 <- lm(pat ~ age + age2)
summary(m2)
##
## Call:
## lm(formula = pat ~ age + age2)
##
## Residuals:
## Min 1Q Median 3Q Max
## -147589 -114678 -62547 3534 1075524
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -94956.50 78284.70 -1.213 0.2257
## age 6447.70 3315.34 1.945 0.0524 .
## age2 -42.85 32.31 -1.326 0.1853
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 189300 on 497 degrees of freedom
## Multiple R-squared: 0.03783, Adjusted R-squared: 0.03396
## F-statistic: 9.77 on 2 and 497 DF, p-value: 6.889e-05
# Représentation de la prédiction du modèle m2
plot(age,pat,xlab = "Âge en années", ylab =
"Patrimoine brut")
curve(coef(m2)[1] + coef(m2)[2]*x + coef(m2)[3] *x^2,add = T)
title(main = "Prédiction du modèle m2")
# Représentation des résidus du modèle m1
plot(age,m2$residuals,xlab = "Âge en années", ylab =
"Résidus du modèle m2")
abline(0,0)
title(main = "Résidus du modèle m2")
sd(m2$residuals[age < 30])
## [1] 62283.16
sd(m2$residuals[age > 50])
## [1] 232932.4
# Installation et chargement du package sandwich
# install.packages("sandwich")
library(sandwich)
# Fonction pour calculée automatiquement les erreurs standards robustes
# Inspiré de : https://thetarzan.wordpress.com/2011/05/28/heteroskedasticity-robust-and-clustered-standard-errors-in-r/
robust <- function(m){
require(sandwich)
n <- nrow(m$model)
p <- ncol(m$model)
std <- (n / (n - p) )*sqrt(diag(sandwich(m)))
t <- m$coefficients/std
pval <- 2*pnorm(-abs(t))
r <- matrix(
c(m$coefficients, std, t, pval)
, nrow=p
, dimnames=dimnames(summary(m)$coefficients)
)
dimnames(r)[[2]][2] <- "Robust std. err."
return(r)
}
# Comparaison des erreurs standards
(t1 <- summary(m2)$coefficients)
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -94956.4960 78284.70409 -1.212964 0.22571994
## age 6447.6972 3315.33867 1.944808 0.05236177
## age2 -42.8501 32.30654 -1.326360 0.18532971
(t2 <- robust(m2))
## Estimate Robust std. err. t value Pr(>|t|)
## (Intercept) -94956.4960 63720.53507 -1.490202 0.13617102
## age 6447.6972 3090.62782 2.086210 0.03695965
## age2 -42.8501 32.81246 -1.305909 0.19158337
# Initialisation du générateur de nombres aléatoires de R
set.seed(1)
# Simulation des variables explicatives
n <- 1000
cons <- 1 * (runif(n) < 0.2)
eff <- round(rchisq(n,14)^2,0)
hr <- eff*rnorm(n,1478,50)
rp <- 1 * (runif(n) + (eff > 49) * 0.1 > 0.6)
pctsy <- pmin(round(rchisq(n,4.5)^1.5,0),100)
# Génération des variables de prévention et d'accident du travail
# l'une et l'autre corrélée au risque inhérent au métier
risque <- rnorm(n)
# Utilisation de la fonction logit pour générer l'indicatrice de prévention
logit <- function(x) exp(x)/(1 + exp(x))
prev <- 1 * (0.50 < logit(-1 + 0.2*risque + 0.6*rp + 0.03*pctsy + 0.2*(eff > 250)) )
summary(prev)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 0.000 0.000 0.000 0.274 1.000 1.000
cor(prev,pctsy)
## [1] 0.534491
cor(prev,rp)
## [1] 0.3805093
# Utilisation d'une loi de Poisson pour générer le nombre d'accidents du travail par établissement
nbAT <- rpois(n,eff*pmax(0.25 + 0.15*risque - 0.05*prev + 0.3*cons - 0.0001*eff,0))
txAT <- nbAT * 1000000/hr
summary(nbAT)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 0.00 18.00 41.00 60.11 79.00 618.00
summary(nbAT/eff)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 0.0000 0.1459 0.2566 0.2819 0.3930 1.0740
summary(txAT)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 0.0 100.6 174.5 190.9 266.9 757.6
cor(nbAT,pctsy)
## [1] -0.01258487
cor(nbAT,rp)
## [1] -0.002652238
# Représentation de la relation entre prévention et txAT
plot(prev,txAT,xlab="Existence d'un dispositif de prévention",ylab="Nombre d'accidents du travail par million d'heures travaillées")
title(main = "Prévention des risques et accidents du travail")
# Estimation du modèle m3
m3 <- lm(txAT ~ prev + cons + eff)
summary(m3)
##
## Call:
## lm(formula = txAT ~ prev + cons + eff)
##
## Residuals:
## Min 1Q Median 3Q Max
## -299.26 -71.97 -4.26 62.39 419.95
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 161.78882 5.53076 29.253 < 2e-16 ***
## prev 38.00129 7.20440 5.275 1.63e-07 ***
## cons 187.26146 7.89109 23.731 < 2e-16 ***
## eff -0.08413 0.01870 -4.499 7.64e-06 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 99.81 on 996 degrees of freedom
## Multiple R-squared: 0.3763, Adjusted R-squared: 0.3744
## F-statistic: 200.3 on 3 and 996 DF, p-value: < 2.2e-16
# Régression de première étape
m4 <- lm(prev ~ rp + pctsy + cons + eff)
summary(m4)
##
## Call:
## lm(formula = prev ~ rp + pctsy + cons + eff)
##
## Residuals:
## Min 1Q Median 3Q Max
## -1.06562 -0.24927 -0.03601 0.18195 0.85225
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -2.612e-01 2.274e-02 -11.487 < 2e-16 ***
## rp 3.618e-01 2.034e-02 17.786 < 2e-16 ***
## pctsy 2.246e-02 9.183e-04 24.459 < 2e-16 ***
## cons -8.374e-03 2.536e-02 -0.330 0.741
## eff 4.622e-04 5.906e-05 7.827 1.28e-14 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.3208 on 995 degrees of freedom
## Multiple R-squared: 0.4854, Adjusted R-squared: 0.4833
## F-statistic: 234.6 on 4 and 995 DF, p-value: < 2.2e-16
# Récupération de la prédiction du modèle 4
prevhat <- m4$fitted.values
# Régression de seconde étape
m5 <- lm(txAT ~ prevhat + cons + eff)
summary(m5)
##
## Call:
## lm(formula = txAT ~ prevhat + cons + eff)
##
## Residuals:
## Min 1Q Median 3Q Max
## -309.27 -69.41 0.56 67.28 403.77
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 172.08063 5.74262 29.966 < 2e-16 ***
## prevhat -23.69201 10.66651 -2.221 0.02656 *
## cons 186.85375 7.98097 23.412 < 2e-16 ***
## eff -0.05412 0.01929 -2.806 0.00512 **
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 100.9 on 996 degrees of freedom
## Multiple R-squared: 0.3621, Adjusted R-squared: 0.3601
## F-statistic: 188.4 on 3 and 996 DF, p-value: < 2.2e-16
# Installation et chargement du package AER
#install.packages("AER")
library("AER")
# Estimation du modèle m6
m6 <- ivreg(txAT ~ prev + cons + eff | rp + pctsy + cons + eff)
summary(m6)
##
## Call:
## ivreg(formula = txAT ~ prev + cons + eff | rp + pctsy + cons +
## eff)
##
## Residuals:
## Min 1Q Median 3Q Max
## -315.299 -73.529 -2.021 71.044 406.016
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 172.08063 5.88337 29.249 < 2e-16 ***
## prev -23.69201 10.92795 -2.168 0.03039 *
## cons 186.85375 8.17659 22.852 < 2e-16 ***
## eff -0.05412 0.01976 -2.739 0.00628 **
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 103.4 on 996 degrees of freedom
## Multiple R-Squared: 0.3304, Adjusted R-squared: 0.3284
## Wald test: 179.5 on 3 and 996 DF, p-value: < 2.2e-16
# Lecture des données et assignation à l'objet e
e <- readRDS(gzcon(url("http://teaching.slmc.fr/mqs2/ee12t4.rds")))
# Passage en minuscule des noms de variables et restriction aux salariés
colnames(e) <- tolower(colnames(e))
e <- e[!is.na(e$salred),]
# Création des variables utilisées dans les modèles
e$lnsalred <- log(e$salred)
e$age2 <- e$age^2
e$femme <- (e$sexe == 2) * 1
e$ddipl1 <- (e$ddipl == 1) * 1 # Diplôme supérieur à baccalauréat + 2 ans
e$ddipl3 <- (e$ddipl == 3) * 1 # Baccalauréat + 2 ans
e$ddipl4 <- (e$ddipl == 4) * 1 # Baccalauréat ou brevet professionnel ou autre diplôme de ce niveau
e$ddipl5 <- (e$ddipl == 5) * 1 # CAP, BEP ou autre diplôme de ce niveau
e$ddipl6 <- (e$ddipl == 6) * 1 # Brevet des collèges
e$ddipl7 <- (e$ddipl == 7) * 1 # Aucun diplôme ou certificat d'études primaires
# Estimation du modèle de référence
m7 <- lm(lnsalred ~ age + age2 + femme + ddipl1 + ddipl3 + ddipl5 + ddipl6 + ddipl7, data = e)
summary(m7)
##
## Call:
## lm(formula = lnsalred ~ age + age2 + femme + ddipl1 + ddipl3 +
## ddipl5 + ddipl6 + ddipl7, data = e)
##
## Residuals:
## Min 1Q Median 3Q Max
## -3.2307 -0.2146 0.0671 0.2927 1.9488
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 5.9391155 0.2305332 25.763 < 2e-16 ***
## age 0.0691972 0.0116498 5.940 4.32e-09 ***
## age2 -0.0006555 0.0001412 -4.641 4.07e-06 ***
## femme -0.3961442 0.0391407 -10.121 < 2e-16 ***
## ddipl1 0.2587343 0.0621396 4.164 3.48e-05 ***
## ddipl3 0.1863284 0.0652343 2.856 0.004402 **
## ddipl5 -0.2074332 0.0568835 -3.647 0.000284 ***
## ddipl6 -0.1825530 0.0955541 -1.910 0.056444 .
## ddipl7 -0.5127076 0.0667608 -7.680 4.84e-14 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.54 on 770 degrees of freedom
## Multiple R-squared: 0.3067, Adjusted R-squared: 0.2995
## F-statistic: 42.58 on 8 and 770 DF, p-value: < 2.2e-16
# Estimation du modèle pondéré
m7w <- lm(lnsalred ~ age + age2 + femme + ddipl1 + ddipl3 + ddipl5 + ddipl6 + ddipl7, data = e, weights = extri1613)
summary(m7w)
##
## Call:
## lm(formula = lnsalred ~ age + age2 + femme + ddipl1 + ddipl3 +
## ddipl5 + ddipl6 + ddipl7, data = e, weights = extri1613)
##
## Weighted Residuals:
## Min 1Q Median 3Q Max
## -135.344 -8.141 2.004 10.491 90.410
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 5.9313057 0.2393566 24.780 < 2e-16 ***
## age 0.0666245 0.0121210 5.497 5.27e-08 ***
## age2 -0.0006081 0.0001470 -4.136 3.93e-05 ***
## femme -0.3767886 0.0398547 -9.454 < 2e-16 ***
## ddipl1 0.3073208 0.0604662 5.083 4.68e-07 ***
## ddipl3 0.2283322 0.0661951 3.449 0.000592 ***
## ddipl5 -0.1805393 0.0578196 -3.122 0.001861 **
## ddipl6 -0.1388831 0.0933496 -1.488 0.137220
## ddipl7 -0.4939485 0.0689624 -7.163 1.85e-12 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 21.17 on 770 degrees of freedom
## Multiple R-squared: 0.3069, Adjusted R-squared: 0.2997
## F-statistic: 42.61 on 8 and 770 DF, p-value: < 2.2e-16