::p_load(tidyverse,sjlabelled,sjPlot,vcd,texreg,ordinal,
pacman
egor,haven,car,dplyr,stargazer,janitor,gridExtra,
ggeffects, kableExtra, questionr, JWileymisc, httr, utils, plotly)
Introducción
Este documento analiza en detalle las redes ego-céntricas utilizando datos de ELSOC 2017 (w2) y 2019 (w4). Construiremos una base de datos que integra información de egos (encuestados) y sus alteri (contactos mencionados), calculando posteriormente medidas de distancia sociodemográfica entre ellos.
Preparación del Entorno
Primero cargaremos las librerías necesarias. El siguiente código utiliza pacman::p_load()
, que tiene la ventaja de instalar los paquetes si no están presentes y luego cargarlos. Cada paquete cumple una función específica:
Carga de Datos
A continuación, cargamos las bases de datos de ELSOC. Estos archivos contienen la información de las olas 2017 y 2019. El formato .RData mantiene la estructura original de los datos, incluyendo etiquetas y metadatos:
#ELSOC 2017
<- "https://github.com/rcantillan/ricantillan.rbind.io/raw/main/dat/ELSOC/ELSOC_W02_v3.00_R.RData"
url <- GET(url)
response <- "ELSOC_W02_v3.00_R.RData"
local_path writeBin(response$content, local_path)
load("ELSOC_W02_v3.00_R.RData")
Preparación de datos
Este paso es crucial para el análisis de redes. Utilizamos rename() para estandarizar el nombre de la variable identificadora en ambas bases de datos. El prefijo ‘.’ en .egoID sigue las convenciones del paquete egor para variables identificadoras:
<- elsoc_2017 %>% rename(.egoID = idencuesta) a
Construcción de Base de Datos de Alteri
Ahora comenzamos la parte más compleja: la construcción de la base de datos de alteri. Para cada alter (contacto mencionado por el ego), necesitamos extraer múltiples características.
Primer Alter
El siguiente código extrae la información del primer alter mencionado por cada ego. Analicemos cada variable seleccionada:
- alter_sexo: Género del contacto (1=Hombre, 2=Mujer)
- alter_edad: Edad en años
- alter_rel: Tipo de relación con ego (1=Familiar, 2=Amigo, etc.)
- alter_tiempo: Duración de la relación
- alter_barrio: Si vive en el mismo barrio que ego
- alter_educ: Nivel educativo
- alter_relig: Afiliación religiosa
- alter_ideol: Orientación política
<- a %>%
alter_1 ::select(.egoID,
dplyralter_sexo=r13_sexo_01, # Recodificamos nombre de variable
alter_edad=r13_edad_01, # para mantener consistencia
alter_rel=r13_relacion_01, # Los sufijos _01 indican
alter_tiempo=r13_tiempo_01, # que corresponden al
alter_barrio=r13_barrio_01, # primer alter mencionado
alter_educ=r13_educ_01,
alter_relig=r13_relig_01,
alter_ideol=r13_ideol_01)
Resto de Alteri
Repetimos el mismo proceso para los alteri 2 al 5. La única diferencia es el sufijo en los nombres de las variables originales (_02, _03, etc.). Este código es repetitivo pero necesario para mantener la claridad en la estructura de los datos:
# Segundo alter - sufijo _02 en variables originales
<- a %>%
alter_2 ::select(.egoID,
dplyralter_sexo=r13_sexo_02,
alter_edad=r13_edad_02,
alter_rel=r13_relacion_02,
alter_tiempo=r13_tiempo_02,
alter_barrio=r13_barrio_02,
alter_educ=r13_educ_02,
alter_relig=r13_relig_02,
alter_ideol=r13_ideol_02)
# Tercer alter - sufijo _03
<- a %>%
alter_3 ::select(.egoID,
dplyralter_sexo=r13_sexo_03,
alter_edad=r13_edad_03,
alter_rel=r13_relacion_03,
alter_tiempo=r13_tiempo_03,
alter_barrio=r13_barrio_03,
alter_educ=r13_educ_03,
alter_relig=r13_relig_03,
alter_ideol=r13_ideol_03)
# Cuarto alter - sufijo _04
<- a %>%
alter_4 ::select(.egoID,
dplyralter_sexo=r13_sexo_04,
alter_edad=r13_edad_04,
alter_rel=r13_relacion_04,
alter_tiempo=r13_tiempo_04,
alter_barrio=r13_barrio_04,
alter_educ=r13_educ_04,
alter_relig=r13_relig_04,
alter_ideol=r13_ideol_04)
# Quinto alter - sufijo _05
<- a %>%
alter_5 ::select(.egoID,
dplyralter_sexo=r13_sexo_05,
alter_edad=r13_edad_05,
alter_rel=r13_relacion_05,
alter_tiempo=r13_tiempo_05,
alter_barrio=r13_barrio_05,
alter_educ=r13_educ_05,
alter_relig=r13_relig_05,
alter_ideol=r13_ideol_05)
Identificación de Alteri
Para mantener el orden de los alteri en nuestra base de datos, creamos una variable numérica que identifica la posición en que fue mencionado cada alter. Esto es crucial para análisis posteriores que consideren el orden de mención:
# Asignamos números identificadores secuenciales
$n <- 1 # Primer alter mencionado
alter_1$n <- 2 # Segundo alter
alter_2$n <- 3 # Tercer alter
alter_3$n <- 4 # Cuarto alter
alter_4$n <- 5 # Quinto alter alter_5
Creación de Base de Datos en Formato Long
Finalmente, combinamos todos los datos de alteri en un único conjunto de datos en formato longitudinal. Este paso es crucial porque:
- Permite un análisis más eficiente
- Facilita la comparación entre alteri
- Es el formato requerido por muchas funciones de análisis de redes
# Combinamos todas las bases de datos de alteri
<- rbind(alter_1, alter_2, alter_3, alter_4, alter_5)
alteris
# Ordenamos por ID de ego para mantener la estructura jerárquica
<- arrange(alteris, .egoID)
alteris
# Creamos un identificador único para cada alter
<- rowid_to_column(alteris, var = ".altID")
alteris
# Convertimos a tibble para mejor manipulación
<- as_tibble(alteris) alteris
Recodificación de Variables
Recodificación de Atributos de Alteri
A continuación, transformamos las variables categóricas de los alteri para facilitar el análisis. Utilizamos la función factor
para convertir las variables en factores y Recode
del paquete car
para recodificar los valores. Esta recodificación es crucial para:
- Simplificar categorías
- Manejar valores perdidos
- Crear categorías interpretables
# Recodificamos nivel educativo
# 1 = básica, 2 = media, 3 = técnica, 4 = universitaria
$alter_educ <- factor(Recode(alteris$alter_educ,
alteris"1=1;2:3=2;4=3;5=4;-999=NA"))
# Recodificamos religión
# 1-5 representan diferentes afiliaciones religiosas
$alter_relig <- factor(Recode(alteris$alter_relig,
alteris"1=1;2=2;3=3;4=4;5=5;-999=NA"))
# Recodificamos ideología política
# 1-6 representan el espectro político de izquierda a derecha
$alter_ideol <- factor(Recode(alteris$alter_ideol,
alteris"1=1;2=2;3=3;4=4;5=5;6=6;-999=NA"))
# Recodificamos edad en grupos etarios
# 1 = 0-18, 2 = 19-29, 3 = 30-40, 4 = 41-51, 5 = 52-62, 6 = 63+
$alter_edad <- factor(Recode(alteris$alter_edad,
alteris"0:18=1;19:29=2;30:40=3;41:51=4;52:62=5;63:100=6"))
# Recodificamos sexo (1 = hombre, 2 = mujer)
$alter_sexo <- factor(Recode(alteris$alter_sexo,
alteris"1=1;2=2"))
Preparación de Datos de Ego
Ahora creamos un dataset con la información de los egos (encuestados). Seleccionamos variables equivalentes a las que tenemos para los alteri para poder hacer comparaciones directas:
# Seleccionamos y renombramos variables de ego
<- a %>%
egos ::select(.egoID, # ID del encuestado
dplyrego_sexo = m0_sexo, # Sexo del encuestado
ego_edad = m0_edad, # Edad del encuestado
ego_ideol = c15, # Ideología política
ego_educ = m01, # Nivel educativo
ego_relig = m38) # Religión
# Convertimos a tibble para mejor manipulación
<- as_tibble(egos) egos
Recodificación de Variables de Ego
Al igual que con los alteri, recodificamos las variables de los egos para asegurar la comparabilidad:
# Recodificamos nivel educativo
# Agrupamos en 4 niveles: básica, media, técnica, universitaria
$ego_educ <- factor(Recode(egos$ego_educ,
egos"1:3=1;4:5=2;6:7=3;8:10=4;-999:-888=NA"))
# Recodificamos religión
# Agrupamos en 5 categorías principales
$ego_relig <- factor(Recode(egos$ego_relig,
egos"1=1;2=2;9=3;7:8=4;3:6=5;-999:-888=NA"))
# Recodificamos ideología política
# Escala de 1-6 donde 1 = extrema izquierda, 6 = extrema derecha
$ego_ideol <- factor(Recode(egos$ego_ideol,
egos"9:10=1;6:8=2;5=3;2:4=4;0:1=5;11:12=6;-999:-888=NA"))
# Recodificamos edad en los mismos grupos que los alteri
$ego_edad <- factor(Recode(egos$ego_edad,
egos"18=1;19:29=2;30:40=3;41:51=4;52:62=5;63:100=6"))
# Recodificamos sexo (1 = hombre, 2 = mujer)
$ego_sexo <- factor(Recode(egos$ego_sexo,
egos"1=1;2=2"))
Unión de Datos de Ego y Alteri
Combinamos las bases de datos de egos y alteri mediante un left join, lo que nos permite mantener todos los alteri y sus correspondientes egos:
# Unimos las bases de datos usando el ID de ego como llave
<- left_join(alteris, egos, by = ".egoID")
obs
# Creamos un indicador de caso
$case <- 1
obs
# Recodificamos valores perdidos
== "-999"] <- NA
obs[obs == "-888"] <- NA obs[obs
Análisis Descriptivos
Descriptivos (alter)
Observamos la frecuencia de las categorias de los atributos de alteris.
kbl(freq(obs$alter_educ)) %>%kable_paper()
n | % | val% | |
---|---|---|---|
1 | 1362 | 11.0 | 17.8 |
2 | 3543 | 28.7 | 46.2 |
3 | 1042 | 8.4 | 13.6 |
4 | 1719 | 13.9 | 22.4 |
NA | 4699 | 38.0 | NA |
kbl(freq(obs$alter_relig))%>%kable_paper()
n | % | val% | |
---|---|---|---|
1 | 4907 | 39.7 | 60.8 |
2 | 1407 | 11.4 | 17.4 |
3 | 1128 | 9.1 | 14.0 |
4 | 251 | 2.0 | 3.1 |
5 | 373 | 3.0 | 4.6 |
NA | 4299 | 34.8 | NA |
kbl(freq(obs$alter_ideol))%>%kable_paper()
n | % | val% | |
---|---|---|---|
1 | 786 | 6.4 | 11.1 |
2 | 191 | 1.5 | 2.7 |
3 | 382 | 3.1 | 5.4 |
4 | 303 | 2.5 | 4.3 |
5 | 759 | 6.1 | 10.7 |
6 | 4644 | 37.6 | 65.7 |
NA | 5300 | 42.9 | NA |
kbl(freq(obs$alter_edad)) %>%kable_paper()
n | % | val% | |
---|---|---|---|
1 | 349 | 2.8 | 4.3 |
2 | 1477 | 11.9 | 18.3 |
3 | 1875 | 15.2 | 23.2 |
4 | 1713 | 13.9 | 21.2 |
5 | 1466 | 11.9 | 18.2 |
6 | 1186 | 9.6 | 14.7 |
NA | 4299 | 34.8 | NA |
kbl(freq(obs$alter_sexo)) %>%kable_paper()
n | % | val% | |
---|---|---|---|
1 | 3388 | 27.4 | 42 |
2 | 4678 | 37.8 | 58 |
NA | 4299 | 34.8 | NA |
Descriptivos (ego)
Observamos la frecuencia de las categorias de los atributos sociodemográficos de ego.
kbl(freq(obs$ego_educ)) %>%kable_paper()
n | % | val% |
---|---|---|
2985 | 24.1 | 24.1 |
5225 | 42.3 | 42.3 |
2010 | 16.3 | 16.3 |
2145 | 17.3 | 17.3 |
kbl(freq(obs$ego_relig))%>%kable_paper()
n | % | val% | |
---|---|---|---|
1 | 6915 | 55.9 | 56.1 |
2 | 2495 | 20.2 | 20.2 |
3 | 1055 | 8.5 | 8.6 |
4 | 485 | 3.9 | 3.9 |
5 | 1380 | 11.2 | 11.2 |
NA | 35 | 0.3 | NA |
kbl(freq(obs$ego_ideol))%>%kable_paper()
n | % | val% | |
---|---|---|---|
1 | 915 | 7.4 | 7.5 |
2 | 1090 | 8.8 | 8.9 |
3 | 2350 | 19.0 | 19.2 |
4 | 1380 | 11.2 | 11.3 |
5 | 1075 | 8.7 | 8.8 |
6 | 5400 | 43.7 | 44.2 |
NA | 155 | 1.3 | NA |
kbl(freq(obs$ego_edad)) %>%kable_paper()
n | % | val% |
---|---|---|
10 | 0.1 | 0.1 |
1865 | 15.1 | 15.1 |
2530 | 20.5 | 20.5 |
2720 | 22.0 | 22.0 |
2870 | 23.2 | 23.2 |
2370 | 19.2 | 19.2 |
kbl(freq(obs$ego_sexo)) %>%kable_paper()
n | % | val% |
---|---|---|
4755 | 38.5 | 38.5 |
7610 | 61.5 | 61.5 |
Las tablas muestran la distribución de frecuencias para cada característica sociodemográfica. Las columnas representan: 1. La categoría de la variable 2. La frecuencia absoluta (número de casos) 3. El porcentaje del total
Esta información nos permite entender la composición de la muestra tanto a nivel de egos como de alteri, y será fundamental para los análisis posteriores de homofilia y distancia social.
Análisis de Homofilia Educativa
Examinamos la homofilia educativa mediante una tabla cruzada entre los niveles educativos de egos y alteri. Primero recodificamos las etiquetas para mejor interpretación:
# Recodificamos etiquetas educativas
<- obs %>%
obs ::mutate(
dplyrego_educ = case_when(
== 1 ~ "básico",
ego_educ == 2 ~ "media",
ego_educ == 3 ~ "técnica",
ego_educ TRUE ~ "universit."
)%>%
) ::mutate(
dplyralter_educ = case_when(
== 1 ~ "básico",
alter_educ == 2 ~ "media",
alter_educ == 3 ~ "técnica",
alter_educ TRUE ~ "universit."
)
)
# Creamos tabla cruzada con porcentajes
<- sjPlot::tab_xtab(
table_cont var.row = obs$ego_educ,
var.col = obs$alter_educ,
title = "Homofilia Educativa en Redes Personales",
show.row.prc = TRUE,
show.summary = TRUE,
show.col.prc = TRUE,
use.viewer = FALSE
) table_cont
ego_educ | alter_educ | Total | |||
---|---|---|---|---|---|
básico | media | técnica | universit. | ||
básico | 570 19.1 % 41.9 % |
825 27.6 % 23.3 % |
89 3 % 8.5 % |
1501 50.3 % 23.4 % |
2985 100 % 24.1 % |
media | 622 11.9 % 45.7 % |
1881 36 % 53.1 % |
336 6.4 % 32.2 % |
2386 45.7 % 37.2 % |
5225 100 % 42.3 % |
técnica | 116 5.8 % 8.5 % |
481 23.9 % 13.6 % |
389 19.4 % 37.3 % |
1024 50.9 % 16 % |
2010 100 % 16.3 % |
universit. | 54 2.5 % 4 % |
356 16.6 % 10 % |
228 10.6 % 21.9 % |
1507 70.3 % 23.5 % |
2145 100 % 17.3 % |
Total | 1362 11 % 100 % |
3543 28.7 % 100 % |
1042 8.4 % 100 % |
6418 51.9 % 100 % |
12365 100 % 100 % |
χ2=1202.528 · df=9 · Cramer's V=0.180 · p=0.000 |
Visualización de Homofilia Educativa
Creamos un heatmap para visualizar los patrones de homofilia educativa:
# Preparamos datos para el heatmap
<- as.data.frame(prop.table(table(obs$ego_educ, obs$alter_educ)))
table colnames(table) <- c("Ego_educ", "Alter_educ", "Prop")
# Formateamos la proporción para mostrar porcentaje con 2 decimales
$tooltip_text <- sprintf(
table"Ego: %s<br>Alter: %s<br>Proporción: %.2f%%",
$Ego_educ,
table$Alter_educ,
table$Prop * 100
table
)
# Creamos el heatmap
<- ggplot(table, aes(Ego_educ, Alter_educ)) +
p geom_tile(aes(fill = Prop, text = tooltip_text)) + # Añadimos el texto para el tooltip
scale_fill_gradient(low = "white", high = "black") +
theme_minimal() +
labs(
title = "Heatmap de Homofilia Educativa",
x = "Nivel Educativo de Ego",
y = "Nivel Educativo de Alter",
fill = "Proporción"
)
# Convertimos a plotly especificando qué variables mostrar en el tooltip
ggplotly(p, tooltip = "text")
Análisis de Relaciones por Tipo
Calculamos promedios de tiempo de relación según el tipo de vínculo:
%>%
obs summarise(
mean.clo.esp = mean(alter_tiempo[alter_rel == "1"], na.rm = TRUE),
mean.clo.hijo = mean(alter_tiempo[alter_rel == "2"], na.rm = TRUE),
mean.clo.pari = mean(alter_tiempo[alter_rel == "3"], na.rm = TRUE),
mean.clo.amig = mean(alter_tiempo[alter_rel == "4"], na.rm = TRUE),
mean.clo.otro = mean(alter_tiempo[alter_rel == "5"], na.rm = TRUE),
count.par.barr = sum((alter_rel == "3" & alter_barrio == "1"), na.rm = TRUE)
%>%
) kbl() %>%
kable_paper()
mean.clo.esp | mean.clo.hijo | mean.clo.pari | mean.clo.amig | mean.clo.otro | count.par.barr |
---|---|---|---|---|---|
4.498406 | 4.91511 | 4.877932 | 4.075097 | 3.67823 | 1215 |
Cálculo de Distancias Sociodemográficas
Creación de Vectores de Distancia
Calculamos medidas de distancia sociodemográfica entre ego y alter. Un valor de 1 indica diferencia en el atributo:
# Calculamos distancias para cada dimensión
$sexo_dist <- ifelse(obs$alter_sexo == obs$ego_sexo, 0, 1)
obs$edad_dist <- ifelse(obs$alter_edad == obs$ego_edad, 0, 1)
obs$educ_dist <- ifelse(obs$alter_educ == obs$ego_educ, 0, 1)
obs$ideol_dist <- ifelse(obs$alter_ideol == obs$ego_ideol, 0, 1)
obs$relig_dist <- ifelse(obs$alter_relig == obs$ego_relig, 0, 1) obs
Resumen de Distancias
Finalmente, presentamos un resumen de las distancias sociodemográficas:
# Creamos tabla resumen de distancias
kbl(egltable(
c("sexo_dist", "edad_dist", "educ_dist", "ideol_dist", "relig_dist"),
data = obs,
strict = TRUE
%>%
)) kable_paper()
M (SD) | |
---|---|
sexo_dist | 0.36 (0.48) |
edad_dist | 0.65 (0.48) |
educ_dist | 0.65 (0.48) |
ideol_dist | 0.55 (0.50) |
relig_dist | 0.38 (0.49) |
Esta tabla final muestra el porcentaje de díadas ego-alter que presentan diferencias en cada dimensión sociodemográfica, permitiéndonos evaluar los patrones de homofilia en diferentes características.
Bibliografía.
Bargsted Valdés, M. A., Espinoza, V., & Plaza, A. (2020). Pautas de Homofilia en Chile. Papers. Revista de Sociologia, 105(4), 583. https://doi.org/10.5565/rev/papers.2617
Smith, J. A., McPherson, M., & Smith-Lovin, L. (2014). Social Distance in the United States: Sex, Race, Religion, Age, and Education Homophily among Confidants, 1985 to 2004. American Sociological Review, 79(3), 432–456. https://doi.org/10.1177/0003122414531776