Capítol 5 Teoria Setmana 5
5.1 Packages
install.packages("visreg")
5.2 Dades de intenció de vot
- Mostra aleatòria de mida n = 800 d’una població
- Variables: despesa, renda, gènere (1/0, home = 1), vot (1/0, partit A = 1)
library(foreign)
data <- read.spss("http://84.89.132.1/~satorra/dades/M2014dadesSIM.sav", to.data.frame = TRUE, use.value.labels = TRUE)
dim(data)## [1] 800 4
library(knitr)
kable(head(head(data)))| Lrenda | Ldespeses | Genere | Vot |
|---|---|---|---|
| 9.477 | 4.503 | 1 | 1 |
| 11.435 | 6.147 | 1 | 0 |
| 10.686 | 4.961 | 0 | 0 |
| 10.407 | 3.993 | 0 | 0 |
| 10.814 | 5.746 | 0 | 0 |
| 9.944 | 4.950 | 0 | 1 |
summary(head(data))## Lrenda Ldespeses Genere Vot
## Min. : 9.477 Min. :3.993 Min. :0.0000 Min. :0.0000
## 1st Qu.:10.060 1st Qu.:4.615 1st Qu.:0.0000 1st Qu.:0.0000
## Median :10.546 Median :4.955 Median :0.0000 Median :0.0000
## Mean :10.460 Mean :5.050 Mean :0.3333 Mean :0.3333
## 3rd Qu.:10.782 3rd Qu.:5.550 3rd Qu.:0.7500 3rd Qu.:0.7500
## Max. :11.435 Max. :6.147 Max. :1.0000 Max. :1.0000
S’observa un 33,3% en la intenció del vot del partit A.
5.2.1 La Regressió lineal
Fins ara, Y era una variable continua. Ara la Y es binaria (pren valors 0 o 1). Segueix essent vàlida la regressió lineal?
Veiem com quedaria la regressió lineal versus la loess.
data %>%
ggplot(aes(Lrenda, Vot))+
geom_jitter(height =0.02)+
geom_smooth(method='lm', se=FALSE, formula = y~x, aes(color = "lm"))+
geom_smooth(method='loess', se=FALSE, formula = y~x, aes(color = "loess"))
Mirem ara el resum de la regressió lineal.
re0 <-lm(Vot ~ Lrenda, data=data)
summary(re0)##
## Call:
## lm(formula = Vot ~ Lrenda, data = data)
##
## Residuals:
## Min 1Q Median 3Q Max
## -1.10516 -0.39910 0.07352 0.37185 1.12443
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 2.89760 0.15615 18.56 <2e-16 ***
## Lrenda -0.23403 0.01549 -15.11 <2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.4392 on 798 degrees of freedom
## Multiple R-squared: 0.2224, Adjusted R-squared: 0.2215
## F-statistic: 228.3 on 1 and 798 DF, p-value: < 2.2e-16
Problemes quan la Y es binaria:
- La relació es no-lineal
- Els termes d’error són heteroscedàstics
- El terme d’error no té distribució normal
plot(re0,1)
plot(re0,2)
5.2.2 La Regressió logística
L’alternativa és el model de regressió logística:
Suposem que \(Y_{i} \sim \mbox{Bernoulli }(p_i)\), \(p_i = P(Y_i = 1), \, i = 1, \dots, n\)
Transformem:
\[p \rightarrow odds(p) \rightarrow Logit(p)\]
on \(odds(p) = p/(1-p)\), en català raó de probabilitats.
\(p \rightarrow odds(p) \equiv p /(1- p) \rightarrow Logit(p) = \ln \, (odds (p)) = \ln \frac{p }{1 - p } \leftrightarrow p = \frac{1}{1 + e^{-L }}\)
Model lineal pel \(L = Logit(p) = \ln \frac{p }{1 - p }\):
\(L = \beta_0 + \beta_1 X_1 + \beta_2 X_2 + \beta_3 X_3\) Model no-lineal per p, on:
\(p \equiv E(Y \mid X_1, X_2, X_3) = \frac{1}{1 + e^{-( \beta_0 + \beta_1 X_1 + \beta_2 X_2 + \beta_3 X_3)}}\)
versus el model de regressió lineal clàssic que diu que \(p = \beta_0 + \beta_1 X_1 + \beta_2 X_2 + \beta_3 X_3\).
Exemple: Y = Vot, X = Lrenda \(P(Y = 1) = p = \frac{1}{1 + e^{-L_i}} = \frac{1}{1 + e^{- (\alpha + \beta * Lrenda)}}\).
re1<-glm(Vot ~ Lrenda, data=data, family = "binomial")
summary(re1)##
## Call:
## glm(formula = Vot ~ Lrenda, family = "binomial", data = data)
##
## Deviance Residuals:
## Min 1Q Median 3Q Max
## -2.5206 -0.9692 0.4540 0.9087 2.5511
##
## Coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) 12.389 1.027 12.07 <2e-16 ***
## Lrenda -1.208 0.101 -11.96 <2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for binomial family taken to be 1)
##
## Null deviance: 1101.02 on 799 degrees of freedom
## Residual deviance: 900.73 on 798 degrees of freedom
## AIC: 904.73
##
## Number of Fisher Scoring iterations: 4
re1 %>% coef()## (Intercept) Lrenda
## 12.388980 -1.208374
\[P(Y = 1) = p = \frac{1}{1 + e^{- (12.388980 - 1.208374 * Lrenda)}}\]
5.2.3 Interpretació dels paràmetres
re1 %>% coef() %>% exp() %>% round(4)## (Intercept) Lrenda
## 240140.5549 0.2987
\(\hat{L} = 12.388980 - 1.208374 * Lrenda\)
\(exp(-1.208374 )= 0.2987 \rightarrow 0.2987 - 1 = -0.7013 \rightarrow odds(p)\)
Decreix un 70% en el canvi de x a X+1 (aproximadament duplicar ingressos ja que estan en escala log).
\((\exp(\beta) - 1)\times100\) =% d’augment/decreixement dels odds
5.2.4 Lineal versus Logística
data <- data %>%
mutate(
P_lm_Vot = 2.8975953 - 0.2340296 * Lrenda
, P_glm_Vot = 1/(1+ exp(-(12.388980 - 1.208374 * Lrenda )))) %>%
arrange(Lrenda )
data %>% select(P_glm_Vot,P_lm_Vot) %>% summary()## P_glm_Vot P_lm_Vot
## Min. :0.02833 Min. :-0.1864
## 1st Qu.:0.36861 1st Qu.: 0.3939
## Median :0.55061 Median : 0.5375
## Mean :0.55000 Mean : 0.5500
## 3rd Qu.:0.75337 3rd Qu.: 0.7145
## Max. :0.97631 Max. : 1.2184
Observem valors poc desitjables negatius i per sobre de 1 en la variable P_lm_Vot. Veiem gràficament
data %>%
ggplot(aes(Lrenda, Vot))+
geom_jitter(width = 0.15, height =0.05)+
geom_smooth(method='lm', se=FALSE, formula = y~x, aes(color = "lm"))+
geom_smooth(method='loess', se=FALSE, formula = y~x, aes(color = "loess"))+
geom_line(aes(y=P_glm_Vot,color = "glm-logit"))+
geom_hline(yintercept=c(0,1))
Observa com la corba obtinguda per la regressió logística (glm-logit) captura millor la tendència observada a través de la regressió Loess. Addicionalment la regressió logística defineix una asímptota respecte el 0 i l’1 (s’acosta, però no arriba a creuar mai).
5.2.5 Regressió logística amb covariants: Lrenda, gènere…
Ajustem un primer model.
suppressPackageStartupMessages(library(stargazer))
#Lineal
re2<-lm(Vot ~ Lrenda + Genere, data=data)
#Logística
re3<-glm(Vot ~ Lrenda + Genere, data=data, family = "binomial")
stargazer(re0,re1,re2, type = "text")##
## ===============================================================================
## Dependent variable:
## -----------------------------------------------------------
## Vot
## OLS logistic OLS
## (1) (2) (3)
## -------------------------------------------------------------------------------
## Lrenda -0.234*** -1.208*** -0.182***
## (0.015) (0.101) (0.014)
##
## Genere 0.460***
## (0.027)
##
## Constant 2.898*** 12.389*** 2.139***
## (0.156) (1.027) (0.142)
##
## -------------------------------------------------------------------------------
## Observations 800 800 800
## R2 0.222 0.425
## Adjusted R2 0.221 0.423
## Log Likelihood -450.366
## Akaike Inf. Crit. 904.732
## Residual Std. Error 0.439 (df = 798) 0.378 (df = 797)
## F Statistic 228.283*** (df = 1; 798) 294.136*** (df = 2; 797)
## ===============================================================================
## Note: *p<0.1; **p<0.05; ***p<0.01
Els coeficients de la part lineal de la regressió logística.
re3 %>% coef() %>% round(2)## (Intercept) Lrenda Genere
## 12.30 -1.32 2.61
Interpretem els coeficients en termes de odds.
re3 %>% coef() %>% exp() %>% round(4) - 1## (Intercept) Lrenda Genere
## 218904.9754 -0.7339 12.6663
- La renta, a igualtat de gènere, ha incrementat en termes absoluts el seu efecte en una disminució de 73% sobre els odds de la intenció de Vot al duplicar els ingressos
- Per altra banda, els homes tenen un 12% d’increment en els odds de la intenció de Vot que les dones, a igualtat d’ingressos.
5.2.6 Regressió logística amb covariants: gràfic d’efectes condicionats
La funció visreg() ens resol la visualització del efecte de cada factor condicionat als valors fixes de la resta de variables (utilitza la mediana en numèriques o la moda en factors).
En aquest cas veiem l’efecte de la renta sobre la intenció de vot, condicionat al gènere.
library(visreg)
visreg(re3, "Lrenda",
by = "Genere",
band = TRUE, # viualitzem bandes
gg = TRUE, # usem ggplot2
overlay=TRUE, # un mateix grafic
scale="response") +
labs(y = "Prob(Vot)",
x = "Lrenda")
Observem com els homes tenen una corba clarament per sobre. També, la variació de la intenció de vot es fa més pronunciada (mes pendent) en les dones en trams de rentes baixes que en homes (efecte no lineal).
També podem retornar la variable de Renta a escala normal (Euros) transformant amb la exponencial.
visreg(re2, "Lrenda",
by = "Genere",
xtrans = exp,
band = TRUE, # viualitzem bandes
gg = TRUE, # usem ggplot2
overlay=TRUE, # un mateix grafic
scale="response") +
labs(y = "Prob(Vot)",
x = "Lrenda")
El canvi d’escala accentua la interpretació anterior, es a dir, major variació en trams de rentes baixes en dones que en homes.
Pots profunditzar en el paràmetres de visreg a l’ajuda:
?visreg # paràmetres dels càlculs.
?plot.visreg # paràmetres del gràfic.
5.3 Exemple de Vtown data
La contaminació per residus tòxics en el terreny de dos escoles públiques. Algunes persones pensaven que l’escola hauria d’estar tancada fins que el terreny fos declarat segur. Altres persones argumentaven que els costos no justificaven el risc i volien que es mantingués oberta l’escola afectada.
SCHOOL: Resposta si volien que l’escola estigués tancada (CLOSE) o oberta (OPEN).
GENDER: Gènere de l’enquestat.
LIVED: Anys de residencia al municipi.
KIDS: L’enquestat té nens, o no.
EDUC: Anys d’estudis de l’enquestat.
MEETINGS: L’enquestat ha anat als mítings sobre crisis provocada per la contaminació.
CONTAM: L’enquestat creu que la seva propietat ha estat contaminada (o no).
Motivació: llegir la noticia Exposició a contaminació de la mare i deficiència en pes (LBW) dels nadons
Les dades.
library(foreign)
da <- as.data.frame(read.spss("http://84.89.132.1/~satorra/dades/VtTown.sav", to.data.frame = TRUE))
head(da)## ID GENDER LIVED KIDS EDUC MEETINGS CONTAM SCHOOL
## 1 1 MALE 35 YES 12 YES YES CLOSE
## 2 2 MALE 5 YES 14 YES NO CLOSE
## 3 3 MALE 21 NO 12 YES YES CLOSE
## 4 4 MALE 6 NO 16 NO NO OPEN
## 5 5 MALE 12 YES 18 NO NO OPEN
## 6 6 MALE 12 YES 16 NO NO OPEN
da %>% count(SCHOOL)## SCHOOL n
## 1 OPEN 87
## 2 CLOSE 66
da <- da %>%
mutate(Y = as.numeric(SCHOOL) -1)
da %>% count(Y)## Y n
## 1 0 87
## 2 1 66
L’objectiu és analitzar la propensió de la intenció de tancar l’escola fins que no es confirmi que està des contaminada.
reg1<- glm(Y ~ LIVED + MEETINGS, binomial, data=da )
summary(reg1)##
## Call:
## glm(formula = Y ~ LIVED + MEETINGS, family = binomial, data = da)
##
## Deviance Residuals:
## Min 1Q Median 3Q Max
## -2.0559 -0.8567 -0.5140 0.6189 2.3832
##
## Coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -0.34850 0.31816 -1.095 0.27336
## LIVED -0.03575 0.01355 -2.638 0.00833 **
## MEETINGSYES 2.36882 0.44298 5.347 8.92e-08 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for binomial family taken to be 1)
##
## Null deviance: 209.21 on 152 degrees of freedom
## Residual deviance: 160.27 on 150 degrees of freedom
## AIC: 166.27
##
## Number of Fisher Scoring iterations: 4
Gràficament,
visreg(reg1, "LIVED",
by = "MEETINGS",
band = TRUE, # viualitzem bandes
gg = TRUE, # usem ggplot2
overlay=TRUE, # un mateix grafic
scale="response") +
labs(y = "Prob(Close)",
x = "LIVED")
Definim un model complert amb un factor de interacció de GENDER y KIDS.
da <- da %>%
mutate(MALE = 1.0*(GENDER=="MALE"))
lreg2 <- glm(Y ~ LIVED + EDUC+ CONTAM+MEETINGS+MALE+KIDS+ KIDS*MALE ,family=binomial, data= da)
summary(lreg2)##
## Call:
## glm(formula = Y ~ LIVED + EDUC + CONTAM + MEETINGS + MALE + KIDS +
## KIDS * MALE, family = binomial, data = da)
##
## Deviance Residuals:
## Min 1Q Median 3Q Max
## -2.6027 -0.7557 -0.3091 0.6316 2.3920
##
## Coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) 2.84216 1.44277 1.970 0.04885 *
## LIVED -0.04664 0.01698 -2.748 0.00600 **
## EDUC -0.20602 0.09320 -2.211 0.02706 *
## CONTAMYES 1.28208 0.48137 2.663 0.00774 **
## MEETINGSYES 2.41800 0.50966 4.744 2.09e-06 ***
## MALE -2.17443 0.81906 -2.655 0.00794 **
## KIDSYES -0.67062 0.56561 -1.186 0.23576
## MALE:KIDSYES 2.22599 0.99911 2.228 0.02588 *
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for binomial family taken to be 1)
##
## Null deviance: 209.21 on 152 degrees of freedom
## Residual deviance: 141.05 on 145 degrees of freedom
## AIC: 157.05
##
## Number of Fisher Scoring iterations: 5
da <- da %>%
mutate(INTER = (1.0*(KIDS=="NO"))*MALE)
lreg3 <- glm(Y ~ LIVED + EDUC + CONTAM + MEETINGS+ INTER ,family=binomial, data= da)
stargazer(lreg2, lreg3, type="text")##
## ==============================================
## Dependent variable:
## ----------------------------
## Y
## (1) (2)
## ----------------------------------------------
## LIVED -0.047*** -0.040**
## (0.017) (0.015)
##
## EDUC -0.206** -0.197**
## (0.093) (0.093)
##
## CONTAMYES 1.282*** 1.299***
## (0.481) (0.477)
##
## MEETINGSYES 2.418*** 2.279***
## (0.510) (0.490)
##
## MALE -2.174***
## (0.819)
##
## KIDSYES -0.671
## (0.566)
##
## MALE:KIDSYES 2.226**
## (0.999)
##
## INTER -1.731**
## (0.725)
##
## Constant 2.842** 2.182
## (1.443) (1.330)
##
## ----------------------------------------------
## Observations 153 153
## Log Likelihood -70.525 -71.326
## Akaike Inf. Crit. 157.049 154.652
## ==============================================
## Note: *p<0.1; **p<0.05; ***p<0.01
Comparem l’ajust dels dos models.
anova( lreg3, lreg2, test = "Chisq")## Analysis of Deviance Table
##
## Model 1: Y ~ LIVED + EDUC + CONTAM + MEETINGS + INTER
## Model 2: Y ~ LIVED + EDUC + CONTAM + MEETINGS + MALE + KIDS + KIDS * MALE
## Resid. Df Resid. Dev Df Deviance Pr(>Chi)
## 1 147 142.65
## 2 145 141.05 2 1.6031 0.4486
Analitzem el canvi d’efecte dels anys de residencia condicionat a tenir (o no) nens, dins del grup d’homes.
visreg(lreg2, "LIVED",
by = "KIDS",
cond=list(MALE=1), # condicionem a ser home
band = TRUE, # viualitzem bandes
gg = TRUE, # usem ggplot2
overlay=TRUE, # un mateix grafic
scale="response") +
labs(y = "Prob(Close)",
x = "LIVED")
5.3.1 Anàlisis bivariant preliminar
Fem un pas enrere. Com en el cas de la regressió lineal, abans de modelitzar, es interesant fer un breu anàlisis bivariant de les variables que es volen introduir en el model.
Veiem un exemple a partir dels quantils de la variable LIVED .
quantile(da$LIVED, seq(0,1,0.2))## 0% 20% 40% 60% 80% 100%
## 1.0 5.0 10.0 20.0 31.6 81.0
A partir del quantils de la variable podem definir una partició de la variable lived.
da <- da %>%
mutate(LIVED_T = cut(LIVED, c(-Inf, 5,10, 20, 32,Inf)))
da %>% count(LIVED_T)## LIVED_T n
## 1 (-Inf,5] 40
## 2 (5,10] 23
## 3 (10,20] 33
## 4 (20,32] 27
## 5 (32, Inf] 30
Mirem-ho ara amb les freqüències relatives de cada fila.
da %>%
group_by(LIVED_T) %>%
summarise(freq_absolutes = n()
,propensio = mean(Y))## # A tibble: 5 x 3
## LIVED_T freq_absolutes propensio
## <fct> <int> <dbl>
## 1 (-Inf,5] 40 0.6
## 2 (5,10] 23 0.522
## 3 (10,20] 33 0.394
## 4 (20,32] 27 0.481
## 5 (32, Inf] 30 0.133
Incorporem els intervals de confiança.
Recorda que la desviació típica de una variable bernoulli(p) on p es la probabilitat de estar Indecís, val:
\[ stdDesv(Y ) = \sqrt{p*q} \]
on q = 1- p.
Per altra banda, l’error estàndard es calcula com:
\[ errStd(Y ) = \sqrt{p*q / n} \]
on n es el nombre observacions.
D’aquesta forma, l’interval de confiança (95%) es defineix com.
\[\left[p - 1.96*\sqrt{p*q / n}, p + 1.96*\sqrt{p*q / n}\right]\]
Ara en R.
errStd_bin <- function(x) { sqrt(mean(x)*(1-mean(x)) / length(x))}
minInt_bin <- function(x) { mean(x) - 1.96 *errStd_bin(x) }
maxInt_bin <- function(x) { mean(x) + 1.96 *errStd_bin(x) }
RESUM <- da %>%
group_by(LIVED_T) %>%
summarise(freq_absolutes = n()
,I_minim = minInt_bin(Y )
,propensio = mean(Y )
,I_maxim = maxInt_bin(Y )) %>%
mutate(freq_relatives = freq_absolutes / sum(freq_absolutes))
RESUM## # A tibble: 5 x 6
## LIVED_T freq_absolutes I_minim propensio I_maxim freq_relatives
## <fct> <int> <dbl> <dbl> <dbl> <dbl>
## 1 (-Inf,5] 40 0.448 0.6 0.752 0.261
## 2 (5,10] 23 0.318 0.522 0.726 0.150
## 3 (10,20] 33 0.227 0.394 0.561 0.216
## 4 (20,32] 27 0.293 0.481 0.670 0.176
## 5 (32, Inf] 30 0.0117 0.133 0.255 0.196
Gràficament,
suppressPackageStartupMessages(library(cowplot))
library(scales)
p1 <- RESUM %>%
ggplot(aes(LIVED_T, freq_relatives)) +
geom_bar(stat="identity")+
geom_text(aes(label = freq_absolutes), vjust=1.6, color="white")+
scale_y_continuous(labels = percent)+
theme_minimal()+
theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1))+
labs(title="Freqüencies")
p2 <- RESUM %>%
ggplot(aes(LIVED_T, propensio)) +
geom_point(size = 1.5) +
geom_errorbar(aes(ymin =I_minim, ymax = I_maxim, width = .2))+
scale_y_continuous(labels = percent)+
theme_minimal()+
theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1))+
labs(title="Intervals confiança Indecisió")
plot_grid(p1, p2, ncol=2)
Mateix anàlisi, sobre la variable MEETINGS :
RESUM <- da %>%
group_by(MEETINGS ) %>%
summarise(freq_absolutes = n()
,I_minim = minInt_bin(Y )
,propensio = mean(Y )
,I_maxim = maxInt_bin(Y )) %>%
mutate(freq_relatives = freq_absolutes / sum(freq_absolutes))
p1 <- RESUM %>%
ggplot(aes(MEETINGS , freq_relatives)) +
geom_bar(stat="identity")+
geom_text(aes(label = freq_absolutes), vjust=1.6, color="white")+
scale_y_continuous(labels = percent)+
theme_minimal()+
theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1))+
labs(title="Freqüencies")
p2 <- RESUM %>%
ggplot(aes(MEETINGS , propensio)) +
geom_point(size = 1.5) +
geom_errorbar(aes(ymin =I_minim, ymax = I_maxim, width = .2))+
scale_y_continuous(labels = percent)+
theme_minimal()+
theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1))+
labs(title="Intervals confiança Indecisió")
plot_grid(p1, p2, ncol=2)