Práctico 08: Regresión lineal, valores predichos e interacciones

Metodología Cuantitativa Avanzada - Magíster en Ciencias Sociales

Fecha de publicación

27 de junio de 2025

Presentación

La siguiente práctica tiene el objetivo de repasar en la interpretación de coeficientes de correlación y la construcción de escalas, así como también en la interpretación de coeficientes de regresión lineal y logística. Para ello, utilizaremos la base de datos de la tercera ola del Estudio Longitudinal Social del Chile 2018 con el objetivo de analizar los determinantes de la Participación Ciudadana.

La versión original de este ejercicio proviene del curso de Estadística multivariada versión 2022.

Librerías

pacman::p_load(dplyr, 
               car, 
               summarytools, 
               sjPlot, 
               texreg, 
               corrplot, 
               ggplot2, 
               sjlabelled, 
               fastDummies, 
               ggeffects)

Datos

El Estudio Longitudinal Social del Chile ELSOC, único en Chile y América Latina, consiste en encuestar a casi 3.000 chilenos, anualmente, a lo largo de una década. ELSOC ha sido diseñado para evaluar la manera cómo piensan, sienten y se comportan los chilenos en torno a un conjunto de temas referidos al conflicto y la cohesión social en Chile. La población objetivo son hombres y mujeres entre 15 y 75 años de edad con un alcance nacional, donde se obtuvo una muestra final de 3748 casos en el año 2018.

#Cargamos la base de datos desde internet
load(url("https://github.com/Kevin-carrasco/metod1-MCS/raw/main/files/data/elsoc2.RData"))

Explorar datos

A partir de la siguiente tabla se obtienen estadísticos descriptivos que luego serán relevantes para realizar las transformaciones y análisis posteriores.

view_df(elsoc,max.len = 50)
Data frame: elsoc
ID Name Label Values Value Labels
1 sexo Sexo entrevistado 0
1
Hombre
Mujer
2 edad Edad entrevistado range: 18-90
3 educ Nivel educacional 1
2
3
4
5
Primaria incompleta menos
Primaria y secundaria baja
Secundaria alta
Terciaria ciclo corto
Terciaria y Postgrado
4 pospol Autoubicacion escala izquierda-derecha 1
2
3
4
Derecha
Centro
Izquierda
Indep./Ninguno
5 part01 Frecuencia: Firma carta o peticion apoyando causa 1
2
3
4
5
Nunca
Casi nunca
A veces
Frecuentemente
Muy frecuentemente
6 part02 Frecuencia: Asiste a mbackground-color:#eeeeeeha o manifestacion
pacifica
1
2
3
4
5
Nunca
Casi nunca
A veces
Frecuentemente
Muy frecuentemente
7 part03 Frecuencia: Participa en huelga 1
2
3
4
5
Nunca
Casi nunca
A veces
Frecuentemente
Muy frecuentemente
8 part04 Frecuencia: Usa redes sociales para opinar en
temas publicos
1
2
3
4
5
Nunca
Casi nunca
A veces
Frecuentemente
Muy frecuentemente
9 inghogar Ingreso total del hogar range: 30000-17000000
10 inghogar_t Ingreso total del hogar (en tramos) 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Menos de $220.000 mensuales liquidos
De $220.001 a $280.000 mensuales liquidos
De $280.001 a $330.000 mensuales liquidos
De $330.001 a $380.000 mensuales liquidos
De $380.001 a $420.000 mensuales liquidos
De $420.001 a $470.000 mensuales liquidos
De $470.001 a $510.000 mensuales liquidos
De $510.001 a $560.000 mensuales liquidos
De $560.001 a $610.000 mensuales liquidos
De $610.001 a $670.000 mensuales liquidos
De $670.001 a $730.000 mensuales liquidos
De $730.001 a $800.000 mensuales liquidos
De $800.001 a $890.000 mensuales liquidos
De $890.001 a $980.000 mensuales liquidos
De $980.001 a $1.100.000 mensuales liquidos
De $1.100.001 a $1.260.000 mensuales liquidos
De $1.260.001 a $1.490.000 mensuales liquidos
De $1.490.001 a $1.850.000 mensuales liquidos
De $1.850.001 a $2.700.000 mensuales liquidos
Mas de $2.700.000 a mensuales liquidos
11 tamhogar Habitantes del hogar range: 1-14

Variable dependiente: participación política

plot_stackfrq(elsoc[,c("part01","part02","part03","part04")]) + theme(legend.position="bottom")

corrplot.mixed(cor(select(elsoc,part01,part02,part03,part04),
                   use = "complete.obs"))

elsoc$part01 <- car::recode(elsoc$part01, "1=0; 2=1; 3=2; 4=3; 5=4")
elsoc$part02 <- car::recode(elsoc$part02, "1=0; 2=1; 3=2; 4=3; 5=4")
elsoc$part03 <- car::recode(elsoc$part03, "1=0; 2=1; 3=2; 4=3; 5=4")
elsoc$part04 <- car::recode(elsoc$part04, "1=0; 2=1; 3=2; 4=3; 5=4")

elsoc <- elsoc %>% mutate(partpol=rowSums(select(., part01,part02,part03,part04)))
summary(elsoc$partpol)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's 
  0.000   0.000   0.000   1.473   2.000  16.000       8 

Variable independiente: ingresos

ingresos hogar variable continua

summary(elsoc$inghogar)
    Min.  1st Qu.   Median     Mean  3rd Qu.     Max.     NA's 
   30000   300000   500000   678843   800000 17000000      668 

ingreso hogar en tramos

sjmisc::frq(elsoc$inghogar_t,
            out = "txt",
            show.na = T) %>% knitr::kable()
val label frq raw.prc valid.prc cum.prc
1 Menos de $220.000 mensuales liquidos 62 1.65 13.00 13.00
2 De $220.001 a $280.000 mensuales liquidos 46 1.23 9.64 22.64
3 De $280.001 a $330.000 mensuales liquidos 57 1.52 11.95 34.59
4 De $330.001 a $380.000 mensuales liquidos 40 1.07 8.39 42.98
5 De $380.001 a $420.000 mensuales liquidos 38 1.01 7.97 50.94
6 De $420.001 a $470.000 mensuales liquidos 37 0.99 7.76 58.70
7 De $470.001 a $510.000 mensuales liquidos 27 0.72 5.66 64.36
8 De $510.001 a $560.000 mensuales liquidos 15 0.40 3.14 67.51
9 De $560.001 a $610.000 mensuales liquidos 24 0.64 5.03 72.54
10 De $610.001 a $670.000 mensuales liquidos 12 0.32 2.52 75.05
11 De $670.001 a $730.000 mensuales liquidos 15 0.40 3.14 78.20
12 De $730.001 a $800.000 mensuales liquidos 16 0.43 3.35 81.55
13 De $800.001 a $890.000 mensuales liquidos 8 0.21 1.68 83.23
14 De $890.001 a $980.000 mensuales liquidos 14 0.37 2.94 86.16
15 De $980.001 a $1.100.000 mensuales liquidos 14 0.37 2.94 89.10
16 De $1.100.001 a $1.260.000 mensuales liquidos 10 0.27 2.10 91.19
17 De $1.260.001 a $1.490.000 mensuales liquidos 7 0.19 1.47 92.66
18 De $1.490.001 a $1.850.000 mensuales liquidos 11 0.29 2.31 94.97
19 De $1.850.001 a $2.700.000 mensuales liquidos 14 0.37 2.94 97.90
20 Mas de $2.700.000 a mensuales liquidos 10 0.27 2.10 100.00
NA NA 3271 87.27 NA NA

podemos obtener la mediana de cada tramo

elsoc$inghogar_t[elsoc$inghogar_t==1] <-(       220000 )    # [1]  "Menos de $220.000 mensuales liquidos"          
elsoc$inghogar_t[elsoc$inghogar_t==2] <-(220001 +280000 )/2 # [2]  "De $220.001 a $280.000 mensuales liquidos"       
elsoc$inghogar_t[elsoc$inghogar_t==3] <-(280001 +330000 )/2 # [3]  "De $280.001 a $330.000 mensuales liquidos"       
elsoc$inghogar_t[elsoc$inghogar_t==4] <-(330001 +380000 )/2 # [4]  "De $330.001 a $380.000 mensuales liquidos"       
elsoc$inghogar_t[elsoc$inghogar_t==5] <-(380001 +420000 )/2 # [5]  "De $380.001 a $420.000 mensuales liquidos"       
elsoc$inghogar_t[elsoc$inghogar_t==6] <-(420001 +470000 )/2 # [6]  "De $420.001 a $470.000 mensuales liquidos"       
elsoc$inghogar_t[elsoc$inghogar_t==7] <-(470001 +510000 )/2 # [7]  "De $470.001 a $510.000 mensuales liquidos"       
elsoc$inghogar_t[elsoc$inghogar_t==8] <-(510001 +560000 )/2 # [8]  "De $510.001 a $560.000 mensuales liquidos"       
elsoc$inghogar_t[elsoc$inghogar_t==9] <-(560001 +610000 )/2 # [9]  "De $560.001 a $610.000 mensuales liquidos"       
elsoc$inghogar_t[elsoc$inghogar_t==10]<-(610001 +670000 )/2 # [10] "De $610.001 a $670.000 mensuales liquidos"       
elsoc$inghogar_t[elsoc$inghogar_t==11]<-(670001 +730000 )/2 # [11] "De $670.001 a $730.000 mensuales liquidos"       
elsoc$inghogar_t[elsoc$inghogar_t==12]<-(730001 +800000 )/2 # [12] "De $730.001 a $800.000 mensuales liquidos"       
elsoc$inghogar_t[elsoc$inghogar_t==13]<-(800001 +890000 )/2 # [13] "De $800.001 a $890.000 mensuales liquidos"       
elsoc$inghogar_t[elsoc$inghogar_t==14]<-(890001 +980000 )/2 # [14] "De $890.001 a $980.000 mensuales liquidos"       
elsoc$inghogar_t[elsoc$inghogar_t==15]<-(980001 +1100000)/2 # [15] "De $980.001 a $1.100.000 mensuales liquidos"      
elsoc$inghogar_t[elsoc$inghogar_t==16]<-(1100001+1260000)/2 # [16] "De $1.100.001 a $1.260.000 mensuales liquidos"    
elsoc$inghogar_t[elsoc$inghogar_t==17]<-(1260001+1490000)/2 # [17] "De $1.260.001 a $1.490.000 mensuales liquidos"    
elsoc$inghogar_t[elsoc$inghogar_t==18]<-(1490001+1850000)/2 # [18] "De $1.490.001 a $1.850.000 mensuales liquidos"    
elsoc$inghogar_t[elsoc$inghogar_t==19]<-(1850001+2700000)/2 # [19] "De $1.850.001 a $2.700.000 mensuales liquidos"    
elsoc$inghogar_t[elsoc$inghogar_t==20]<-(2700000)           # [20] "Mas de $2.700.000 a mensuales liquidos"

y luego imputar este valor medio a los casos NA

elsoc$inghogar_i <- ifelse(test = (is.na(elsoc$inghogar)), #¿existen NA en ingresos?
                           yes = elsoc$inghogar_t,         #VERDADERO, remplazar con la media del tramo
                           no = elsoc$inghogar)            #FALSE, mantener la variable original.

elsoc$inghogar_i <- set_label(elsoc$inghogar_i,"Ingreso total del hogar (imputada)")
elsoc$ing_pcap <- elsoc$inghogar_i/elsoc$tamhogar
elsoc$ing_pcap <- set_label(elsoc$ing_pcap,"Ingreso per cápita del hogar")
elsoc$quintile<- dplyr::ntile(x = elsoc$ing_pcap,
                              n = 5) # n de categorias, para quintiles usamos 5 
elsoc$quintile <- factor(elsoc$quintile,c(1,2,3,4,5), c("Quintil 1","Quintil 2","Quintil 3","Quintil 4","Quintil 5")) 
elsoc %>% 
  group_by(quintile) %>% 
  summarise(n=n(),
            Media=mean(ing_pcap,na.rm = T),
            Mediana=median(ing_pcap,na.rm = T)) %>% 
  knitr::kable()
quintile n Media Mediana
Quintil 1 711 62859.09 66666.67
Quintil 2 711 112218.97 111250.12
Quintil 3 710 167748.23 166666.67
Quintil 4 710 262710.27 250000.50
Quintil 5 710 710246.41 500000.00
NA 196 NaN NA
elsoc$quintilemiss <- factor(elsoc$quintile,ordered = T)
elsoc$quintilemiss <- ifelse(test=is.na(elsoc$quintilemiss),yes = 6,no = elsoc$quintilemiss)
elsoc$quintilemiss <- factor(elsoc$quintilemiss ,levels = c(1,2,3,4,5,6),labels =  c("Quintil 1","Quintil 2","Quintil 3","Quintil 4","Quintil 5","Missing")) 
elsoc %>% group_by(quintilemiss) %>% summarise(n=n())
# A tibble: 6 × 2
  quintilemiss     n
  <fct>        <int>
1 Quintil 1      711
2 Quintil 2      711
3 Quintil 3      710
4 Quintil 4      710
5 Quintil 5      710
6 Missing        196

Regresión lineal

veamos primero las diferencias de usar cada tipo de variable de ingreso

fit01<- lm(partpol~ing_pcap,data=elsoc)
fit02<- lm(partpol~quintile,data=elsoc)
fit03<- lm(partpol~quintilemiss,data=elsoc)
labs01 <- c("Intercepto","Ingreso per/cap",
            "Quintil 2","Quintil 3","Quintil 4","Quintil 5",
            "Quintil 2","Quintil 3","Quintil 4","Quintil 5","Quintil perdido")
#screenreg para que se vea en R
screenreg(list(fit01,fit02,fit03),custom.coef.names = labs01)
# htmlreg para que se vea en el sitio web
knitreg(list(fit01,fit02,fit03),
        custom.model.names = c("Modelo 1","Modelo 2","Modelo 3"),
        custom.coef.names = labs01)
Statistical models
  Modelo 1 Modelo 2 Modelo 3
Intercepto 1.25*** 0.99*** 0.99***
  (0.05) (0.08) (0.09)
Ingreso per/cap 0.00***    
  (0.00)    
Quintil 2   0.19 0.19
    (0.12) (0.12)
Quintil 3   0.51*** 0.51***
    (0.12) (0.12)
Quintil 4   0.60*** 0.60***
    (0.12) (0.12)
Quintil 5   1.08*** 1.08***
    (0.12) (0.12)
Quintil perdido     0.66***
      (0.18)
R2 0.01 0.03 0.02
Adj. R2 0.01 0.03 0.02
Num. obs. 3546 3546 3740
***p < 0.001; **p < 0.01; *p < 0.05

El tercer modelo, con el quintil de casos perdidos, es el que entrega más información y además tiene mayor cantidad de casos (3740).

fit04<- lm(partpol~sexo,data=elsoc)
fit05<- lm(partpol~sexo+edad,data=elsoc)
fit06<- lm(partpol~sexo+edad+quintilemiss,data=elsoc)
fit07<- lm(partpol~sexo+edad+quintilemiss+pospol,data=elsoc)

labs02 <- c("Intercepto","Sexo (mujer=1)","Edad",
            "Quintil 2","Quintil 3","Quintil 4","Quintil 5","Quintil perdido",
            "Centro (ref. derecha)","Izquierda","Idep./Ninguno")
screenreg(list(fit04,fit05,fit06, fit07),custom.coef.names = labs02)
knitreg(list(fit04,fit05,fit06, fit07),
        custom.model.names = c("Modelo 1","Modelo 2","Modelo 3", "Modelo 4"),
        custom.coef.names = c("Intercepto",
                              "Sexo (mujer=1)",
                              "Edad",
                              "Quintil 2",
                              "Quintil 3",
                              "Quintil 4",
                              "Quintil 5",
                              "Quintil perdido",
                              "Centro (ref. derecha)",
                              "Izquierda",
                              "Indep./Ninguno"))
Statistical models
  Modelo 1 Modelo 2 Modelo 3 Modelo 4
Intercepto 1.56*** 3.62*** 3.03*** 3.97***
  (0.06) (0.12) (0.15) (0.16)
Sexo (mujer=1) -0.13 -0.08 0.07 0.12
  (0.08) (0.07) (0.07) (0.07)
Edad   -0.04*** -0.04*** -0.04***
    (0.00) (0.00) (0.00)
Quintil 2     0.23* 0.21
      (0.12) (0.11)
Quintil 3     0.51*** 0.51***
      (0.12) (0.11)
Quintil 4     0.56*** 0.50***
      (0.12) (0.11)
Quintil 5     1.02*** 0.88***
      (0.12) (0.12)
Quintil perdido     0.51** 0.59***
      (0.18) (0.18)
Centro (ref. derecha)       -1.04***
        (0.10)
Izquierda       -1.13***
        (0.11)
Indep./Ninguno       -1.60***
        (0.10)
R2 0.00 0.09 0.11 0.17
Adj. R2 0.00 0.09 0.11 0.17
Num. obs. 3740 3740 3740 3656
***p < 0.001; **p < 0.01; *p < 0.05

El Modelo 1 indica que las mujeres participan 0.13 unidades menos en comparación con los hombres, sin embargo, esta relación no es estadísticamente significativa (p>0.05).

El Modelo 2 indica que por cada unidad que aumenta la edad, la participación política disminuye en promedio 0.04 unidades, con un 99.9% de significación estadístico y manteniendo el sexo constante. Esta relación es consistente en los otros dos modelos.

El Modelo 3 indica que en medida que aumenta el ingreso, la participación política tiende a ser más alta. En específico, en comparación con el menor quintil de ingreso, al pertenecer a un quintil de ingreso 2 (p<0.05), 3, 4 y 5 (p<0.001), la participación política aumenta, manteniendo el resto de las variables constantes. Este efecto disminuye un poco en el modelo siguiente, pero mantiene un efecto lineal (a mayor quintil, mayor participación).

En el Modelo 4 que incluye la posición política de los/as encuestados, la participación política de las personas de izquierda, centro o independiente/ninguno es menor en comparación con las personas de derecha, con una significación estadística del 99.9%, manteniendo el resto de las variables constantes.

Cálculo de valores predichos

  • Paquete ggeffects de R: últil para estimar Valores predichos a partir de modelos de regresión

  • Combinado con ggplot2, se pueden generar gráficos que muestran de modo más intuitivo la relación entre variables

knitreg(list(fit04), 
        custom.model.names = c("Modelo 1"),
        custom.coef.names = c("Intercepto",
                              "Sexo (mujer=1)"))
Statistical models
  Modelo 1
Intercepto 1.56***
  (0.06)
Sexo (mujer=1) -0.13
  (0.08)
R2 0.00
Adj. R2 0.00
Num. obs. 3740
***p < 0.001; **p < 0.01; *p < 0.05
ggeffects::ggpredict(fit04, terms = c("sexo")) %>%
  ggplot(aes(x=x, y=predicted)) +
  geom_bar(stat="identity", color="grey", fill="grey")+
  geom_errorbar(aes(ymin = conf.low, ymax = conf.high), width=.1) +
  labs(title="Sexo", x = "", y = "") +
  theme_bw() +
  scale_x_continuous(name = "",
                     breaks = c(0,1),
                     labels = c("Hombre", "Mujer"))+
  scale_y_continuous(limits = c(0,16), 
                     breaks = seq(0,16, by = 1))

knitreg(list(fit07),
        custom.model.names = c("Modelo 4"),
        custom.coef.names = c("Intercepto",
                              "Sexo (mujer=1)",
                              "Edad",
                              "Quintil 2",
                              "Quintil 3",
                              "Quintil 4",
                              "Quintil 5",
                              "Quintil perdido",
                              "Centro (ref. derecha)",
                              "Izquierda",
                              "Indep./Ninguno"))
Statistical models
  Modelo 4
Intercepto 3.97***
  (0.16)
Sexo (mujer=1) 0.12
  (0.07)
Edad -0.04***
  (0.00)
Quintil 2 0.21
  (0.11)
Quintil 3 0.51***
  (0.11)
Quintil 4 0.50***
  (0.11)
Quintil 5 0.88***
  (0.12)
Quintil perdido 0.59***
  (0.18)
Centro (ref. derecha) -1.04***
  (0.10)
Izquierda -1.13***
  (0.11)
Indep./Ninguno -1.60***
  (0.10)
R2 0.17
Adj. R2 0.17
Num. obs. 3656
***p < 0.001; **p < 0.01; *p < 0.05
ggeffects::ggpredict(fit07, terms = c("quintilemiss")) %>%
  ggplot(aes(x=x, y=predicted)) +
  geom_bar(stat="identity", color="grey", fill="grey")+
  geom_errorbar(aes(ymin = conf.low, ymax = conf.high), width=.1) +
  labs(title="Quintil ingresos", x = "", y = "") +
  theme_bw() +
  scale_x_discrete(name = "",
                   labels = c("Quintil 1", "Quintil 2", "Quintil 3", "Quintil 4", "Quintil 5", "Quintil perdido")) +
  scale_y_continuous(limits = c(0,16), 
                     breaks = seq(0,16, by = 1))

ggeffects::ggpredict(fit07, terms = c("pospol")) %>%
  ggplot(aes(x=x, y=predicted)) +
  geom_bar(stat="identity", color="grey", fill="grey")+
  geom_errorbar(aes(ymin = conf.low, ymax = conf.high), width=.1) +
  labs(title="Posición política", x = "", y = "") +
  theme_bw() +
  scale_x_discrete(name = "",
                   labels = c("Derecha", "Centro", "Izquierda", "Independiente/ninguno")) +
  scale_y_continuous(limits = c(0,16), 
                     breaks = seq(0,16, by = 1))

ggeffects::ggpredict(fit07, terms="edad") %>%
  ggplot(mapping=aes(x = x, y=predicted)) +
  labs(title="Edad", x = "", y = "")+
  theme_bw() +
  geom_smooth()+
  geom_ribbon(aes(ymin = conf.low, ymax = conf.high), alpha = .2, fill = "black") +
  scale_x_continuous(breaks = seq(0,100, by = 10))+
  scale_y_continuous(limits = c(0,16), 
                     breaks = seq(0,16, by = 1))
`geom_smooth()` using method = 'loess' and formula = 'y ~ x'

Interacciones

fit08<- lm(partpol~sexo+edad+quintilemiss+pospol*edad,data=elsoc)
sjPlot::tab_model(fit07,fit08, show.ci = FALSE, pred.labels=c("Intercepto",
                              "Sexo (mujer=1)",
                              "Edad",
                              "Quintil 2",
                              "Quintil 3",
                              "Quintil 4",
                              "Quintil 5",
                              "Quintil perdido",
                              "Centro (ref. derecha)",
                              "Izquierda",
                              "Indep./Ninguno",
                              "Centro * Edad",
                              "Izquierda * Edad",
                              "Indep./Ninguno * Edad"))
  partpol partpol
Predictors Estimates p Estimates p
Intercepto 3.97 <0.001 5.47 <0.001
Sexo (mujer=1) 0.12 0.107 0.11 0.147
Edad -0.04 <0.001 -0.07 <0.001
Quintil 2 0.21 0.059 0.20 0.074
Quintil 3 0.51 <0.001 0.47 <0.001
Quintil 4 0.50 <0.001 0.47 <0.001
Quintil 5 0.88 <0.001 0.86 <0.001
Quintil perdido 0.59 0.001 0.57 0.001
Centro (ref. derecha) -1.04 <0.001 -2.87 <0.001
Izquierda -1.13 <0.001 -2.72 <0.001
Indep./Ninguno -1.60 <0.001 -3.84 <0.001
Centro * Edad 0.04 <0.001
Izquierda * Edad 0.03 <0.001
Indep./Ninguno * Edad 0.05 <0.001
Observations 3656 3656
R2 / R2 adjusted 0.175 / 0.172 0.190 / 0.187

En comparación con las personas de Derecha, el efecto negativo de la edad no es tan pronunciado en personas de Centro, Izquierda o independientes.

sjPlot::plot_model(fit08, type = "int") +
  theme_bw() +
  theme(legend.position = "bottom")

En el fondo lo que muestra el gráfico es que el efecto negativo de la edad es mucho mayor en personas de derecha. O el efecto negativo de la edad es más tenue en personas de centro, izquierda o independientes. U otra opción aún: los jóvenes de derecha son los que más participan. ¿Decepción post estallido en los demás?