¡Bienvenido a este tutorial sobre estadística descriptiva en R! La estadística descriptiva es la rama de la estadística que recolecta, analiza y caracteriza un conjunto de datos (peso de la población, beneficios diarios de una empresa, temperatura mensual, etc.) con el objetivo de describir las características y comportamientos de este conjunto mediante medidas de resumen, tablas o gráficos.
En este tutorial, aprenderás a:
Primero, vamos a cargar las librerías que necesitaremos y a crear un
conjunto de datos de ejemplo. Los paquetes que usaremos son
dplyr para la manipulación de datos y ggplot2
para las gráficas. knitr se usa para crear tablas bien
formateadas.
NOTA: Al guardar la base CAP_modif en formato Excel los factores se convirtieron en character. Abrir la base de datos “CAP_modif” y hacer una copia que llame “datos”
# Cargar la librería
library(readxl)
# Usamos (read_excel) para leer el archivo
# R buscará el archivo en el directorio de tu proyecto actual
CAP_modif <- read_excel("CAP_modif.xlsx")
View(CAP_modif)
# Hacemos una copia idéntica con otro nombre por ejemplo "datos"
datos <- CAP_modifAhora debemos volver a convertir las variables categóricas en factores, no es necesario etiquetar porque ya tienen etiquetas.
## tibble [515 × 92] (S3: tbl_df/tbl/data.frame)
## $ id : num [1:515] 1 2 3 4 5 6 7 8 9 10 ...
## $ part_prev : chr [1:515] "No" "Sí" "No" "No" ...
## $ municipio : chr [1:515] "Santa Tecla" "Santa Tecla" "Santa Tecla" "Santa Tecla" ...
## $ edad : num [1:515] 52 50 27 50 47 47 33 21 37 29 ...
## $ genero : chr [1:515] "Femenino" "Masculino" "Femenino" "Masculino" ...
## $ nivel_edu : chr [1:515] "Nunca asistió" "Primer ciclo" "Bachillerato" "Tercer ciclo" ...
## $ enf_cro : chr [1:515] "No" "Sí" "No" "No" ...
## $ hipertension : chr [1:515] "No" "No" "No" "No" ...
## $ diabetes : chr [1:515] "No" "Sí" "No" "No" ...
## $ epoc : chr [1:515] "No" "No" "No" "No" ...
## $ renal : chr [1:515] "No" "No" "No" "No" ...
## $ artritis : chr [1:515] "No" "No" "No" "No" ...
## $ cardiopatia : chr [1:515] "No" "No" "No" "No" ...
## $ hipotiroidismo : chr [1:515] "No" "No" "No" "No" ...
## $ glaucoma : chr [1:515] "No" "No" "No" "No" ...
## $ lupus : chr [1:515] "No" "No" "No" "No" ...
## $ ulcera_venosa : chr [1:515] "No" "No" "No" "No" ...
## $ ninguna : logi [1:515] NA NA NA NA NA NA ...
## $ area : chr [1:515] "Urbana" "Rural" "Rural" "Urbana" ...
## $ hijxs : chr [1:515] "Sí" "Sí" "Sí" "No" ...
## $ nucleo : num [1:515] 5 2 5 3 4 5 3 2 3 3 ...
## $ empleo : chr [1:515] "Desempleo" "Empleo" "Desempleo" "Empleo" ...
## $ ocupacion : chr [1:515] "Desempleo" "Empleada(o) permanente" "Desempleo" "Trabajo por cuenta propia sin local" ...
## $ ingreso : chr [1:515] "Menos de 365" "Prefiero no contestar" "366 a 730" "Menos de 365" ...
## $ prev_per : chr [1:515] "No" "No, sabe" "No" "No" ...
## $ rec_apoyo : chr [1:515] NA "No" NA NA ...
## $ satisfaccion : chr [1:515] NA NA NA NA ...
## $ prev_fam : chr [1:515] "Sí, hubo sospecha pero no se hizo la prueba" "No" "No" "No" ...
## $ mortalidad : chr [1:515] "No" "No" "No" "No" ...
## $ c1 : num [1:515] 3 1 1 1 1 1 1 1 1 1 ...
## $ c2 : num [1:515] 2 1 1 1 1 1 1 1 1 1 ...
## $ c3 : num [1:515] 3 1 3 1 1 3 1 3 3 1 ...
## $ c4 : num [1:515] 1 1 1 1 1 1 1 3 3 1 ...
## $ c5 : num [1:515] 1 3 1 1 3 1 3 3 3 2 ...
## $ c6 : num [1:515] 1 1 2 1 1 2 1 2 2 1 ...
## $ c7 : num [1:515] 3 3 2 2 3 1 1 3 1 1 ...
## $ c8 : num [1:515] 1 1 1 1 1 1 1 1 1 1 ...
## $ c9 : num [1:515] 1 1 2 1 1 1 1 1 1 1 ...
## $ c10 : num [1:515] 2 1 1 2 1 1 1 1 1 1 ...
## $ a1 : num [1:515] 5 4 5 5 4 3 4 3 2 5 ...
## $ a2 : num [1:515] 5 5 5 5 4 3 4 3 5 5 ...
## $ a3 : num [1:515] 1 2 5 5 3 1 4 1 2 4 ...
## $ a4 : num [1:515] 5 5 5 5 4 5 4 5 5 4 ...
## $ a5 : num [1:515] 1 3 5 1 4 4 4 1 3 4 ...
## $ p1 : num [1:515] 5 3 5 5 1 4 3 3 3 2 ...
## $ p2 : num [1:515] 2 0 3 3 0 2 0 2 2 0 ...
## $ p3 : num [1:515] 3 0 2 3 0 3 0 2 2 0 ...
## $ p4 : num [1:515] 5 1 5 3 1 3 1 3 3 1 ...
## $ p5 : num [1:515] 5 1 3 2 3 3 3 2 5 3 ...
## $ dosis : num [1:515] 3 3 4 3 2 2 2 1 4 3 ...
## $ razon_nv : chr [1:515] "Razón 5" "Razón 6" "Razón 1" "Razón 6" ...
## $ periodico : chr [1:515] "Sí" "No" "No" "Sí" ...
## $ television : chr [1:515] "Sí" "Sí" "Sí" "Sí" ...
## $ redes_sociales : chr [1:515] "No" "Sí" "Sí" "No" ...
## $ personal_salud : chr [1:515] "No" "No" "No" "No" ...
## $ radio : chr [1:515] "Sí" "No" "Sí" "No" ...
## $ paginas_internet : chr [1:515] "No" "No" "Sí" "Sí" ...
## $ escuela : chr [1:515] "Sí" "No" "No" "No" ...
## $ mensajes : chr [1:515] "Sí" "Sí" "Sí" "Sí" ...
## $ patrocinio : chr [1:515] "Otras empresas privadas" "Asociación Salvadoreña Promotora de la Salud (ASPS)" "No recuerda" "Ministerio de Salud/Gobierno central" ...
## $ uso_de_mascarilla : chr [1:515] "Sí" "Sí" "Sí" "Sí" ...
## $ distanciamiento_social : chr [1:515] "Sí" "No" "Sí" "Sí" ...
## $ lavado_de_manos : chr [1:515] "No" "Sí" "Sí" "No" ...
## $ ponerse_la_vacuna : chr [1:515] "Si" "No" "No" "Si" ...
## $ no_recuerdo : chr [1:515] "No" "No" "No" "No" ...
## $ todas : chr [1:515] "No" "No" "No" "No" ...
## $ No_he_escuchado : chr [1:515] "No" "No" "No" "No" ...
## $ transmite_por_el_agua : chr [1:515] "Si" "No" "No" "Si" ...
## $ transmite_en_las_suelas: chr [1:515] "Sí" "No" "No" "Sí" ...
## $ rociar_desinfectantes : chr [1:515] "Sí" "No" "Sí" "Sí" ...
## $ beben_alcohol : chr [1:515] "No" "No" "No" "Sí" ...
## $ pueden_dejar_de_aplicar: chr [1:515] "Sí" "No" "No" "No" ...
## $ no_se_debe_vacunar : chr [1:515] "No" "No" "Sí" "Sí" ...
## $ producen_esterilidad : chr [1:515] "No" "No" "No" "No" ...
## $ producen_homosexualidad: chr [1:515] "No" "Sí" "No" "No" ...
## $ inyectan_el_virus : chr [1:515] "No" "No" "Sí" "Sí" ...
## $ antibioticos_son_buenos: chr [1:515] "No" "No" "No" "Sí" ...
## $ vitaminas_y_minerales : chr [1:515] "No" "No" "No" "No" ...
## $ entrevistadoras : num [1:515] 2 1 2 2 1 2 1 2 2 1 ...
## $ puntaje_A : num [1:515] 17 19 25 21 19 16 20 13 17 22 ...
## $ c1recod : num [1:515] 0 1 1 1 1 1 1 1 1 1 ...
## $ c2recod : num [1:515] 0 1 1 1 1 1 1 1 1 1 ...
## $ c3recod : num [1:515] 0 1 0 1 1 0 1 0 0 1 ...
## $ c4recod : num [1:515] 1 1 1 1 1 1 1 0 0 1 ...
## $ c5recod : num [1:515] 1 0 1 1 0 1 0 0 0 0 ...
## $ c6recod : num [1:515] 1 1 0 1 1 0 1 0 0 1 ...
## $ c7recod : num [1:515] 0 0 0 0 0 1 1 0 1 1 ...
## $ c8recod : num [1:515] 1 1 1 1 1 1 1 1 1 1 ...
## $ c9recod : num [1:515] 1 1 0 1 1 1 1 1 1 1 ...
## $ c10recod : num [1:515] 0 1 1 0 1 1 1 1 1 1 ...
## $ puntaje_C : num [1:515] 5 8 6 8 8 8 9 5 6 9 ...
## $ puntaje_P : num [1:515] 20 5 18 16 5 15 7 12 15 6 ...
# Usamos 'across()' para aplicar la función 'as.factor' a todas las columnas 'where(is.character)'
datos <- datos %>%
mutate(across(where(is.character), as.factor))
# Verificamos la estructura para confirmar que ahora son factores
str(datos)## tibble [515 × 92] (S3: tbl_df/tbl/data.frame)
## $ id : num [1:515] 1 2 3 4 5 6 7 8 9 10 ...
## $ part_prev : Factor w/ 2 levels "No","Sí": 1 2 1 1 1 1 2 1 2 1 ...
## $ municipio : Factor w/ 7 levels "Antiguo Cuscatlán",..: 6 6 6 6 6 6 6 6 6 6 ...
## $ edad : num [1:515] 52 50 27 50 47 47 33 21 37 29 ...
## $ genero : Factor w/ 2 levels "Femenino","Masculino": 1 2 1 2 1 2 1 1 2 2 ...
## $ nivel_edu : Factor w/ 7 levels "Bachillerato",..: 2 3 1 6 6 4 1 6 4 1 ...
## $ enf_cro : Factor w/ 3 levels "No","No sabe",..: 1 3 1 1 3 3 1 1 3 1 ...
## $ hipertension : Factor w/ 2 levels "No","Sí": 1 1 1 1 2 2 1 1 2 1 ...
## $ diabetes : Factor w/ 2 levels "No","Sí": 1 2 1 1 1 2 1 1 1 1 ...
## $ epoc : Factor w/ 2 levels "No","Sí": 1 1 1 1 1 1 1 1 1 1 ...
## $ renal : Factor w/ 2 levels "No","Sí": 1 1 1 1 1 1 1 1 1 1 ...
## $ artritis : Factor w/ 2 levels "No","Sí": 1 1 1 1 1 1 1 1 1 1 ...
## $ cardiopatia : Factor w/ 2 levels "No","Sí": 1 1 1 1 1 1 1 1 1 1 ...
## $ hipotiroidismo : Factor w/ 2 levels "No","Sí": 1 1 1 1 1 1 1 1 1 1 ...
## $ glaucoma : Factor w/ 2 levels "No","Sí": 1 1 1 1 1 1 1 1 1 1 ...
## $ lupus : Factor w/ 2 levels "No","Sí": 1 1 1 1 1 1 1 1 1 1 ...
## $ ulcera_venosa : Factor w/ 2 levels "No","Sí": 1 1 1 1 1 1 1 1 1 1 ...
## $ ninguna : logi [1:515] NA NA NA NA NA NA ...
## $ area : Factor w/ 2 levels "Rural","Urbana": 2 1 1 2 2 1 2 1 2 2 ...
## $ hijxs : Factor w/ 2 levels "No","Sí": 2 2 2 1 2 2 2 2 2 2 ...
## $ nucleo : num [1:515] 5 2 5 3 4 5 3 2 3 3 ...
## $ empleo : Factor w/ 4 levels "Desempleo","Empleo",..: 1 2 1 2 2 1 2 1 2 2 ...
## $ ocupacion : Factor w/ 11 levels "Agricultura",..: 2 4 2 11 11 2 10 2 4 4 ...
## $ ingreso : Factor w/ 5 levels "366 a 730","731 a 1,000",..: 4 5 1 4 5 4 2 4 1 5 ...
## $ prev_per : Factor w/ 4 levels "No","No, sabe",..: 1 2 1 1 1 1 1 1 4 4 ...
## $ rec_apoyo : Factor w/ 3 levels "No","Sí, del ISSS",..: NA 1 NA NA NA NA NA NA 2 2 ...
## $ satisfaccion : Factor w/ 3 levels "Buena","excelente",..: NA NA NA NA NA NA NA NA 1 2 ...
## $ prev_fam : Factor w/ 4 levels "No","No sabe",..: 3 1 1 1 1 2 1 2 4 4 ...
## $ mortalidad : Factor w/ 2 levels "No","Sí": 1 1 1 1 1 1 1 1 2 1 ...
## $ c1 : num [1:515] 3 1 1 1 1 1 1 1 1 1 ...
## $ c2 : num [1:515] 2 1 1 1 1 1 1 1 1 1 ...
## $ c3 : num [1:515] 3 1 3 1 1 3 1 3 3 1 ...
## $ c4 : num [1:515] 1 1 1 1 1 1 1 3 3 1 ...
## $ c5 : num [1:515] 1 3 1 1 3 1 3 3 3 2 ...
## $ c6 : num [1:515] 1 1 2 1 1 2 1 2 2 1 ...
## $ c7 : num [1:515] 3 3 2 2 3 1 1 3 1 1 ...
## $ c8 : num [1:515] 1 1 1 1 1 1 1 1 1 1 ...
## $ c9 : num [1:515] 1 1 2 1 1 1 1 1 1 1 ...
## $ c10 : num [1:515] 2 1 1 2 1 1 1 1 1 1 ...
## $ a1 : num [1:515] 5 4 5 5 4 3 4 3 2 5 ...
## $ a2 : num [1:515] 5 5 5 5 4 3 4 3 5 5 ...
## $ a3 : num [1:515] 1 2 5 5 3 1 4 1 2 4 ...
## $ a4 : num [1:515] 5 5 5 5 4 5 4 5 5 4 ...
## $ a5 : num [1:515] 1 3 5 1 4 4 4 1 3 4 ...
## $ p1 : num [1:515] 5 3 5 5 1 4 3 3 3 2 ...
## $ p2 : num [1:515] 2 0 3 3 0 2 0 2 2 0 ...
## $ p3 : num [1:515] 3 0 2 3 0 3 0 2 2 0 ...
## $ p4 : num [1:515] 5 1 5 3 1 3 1 3 3 1 ...
## $ p5 : num [1:515] 5 1 3 2 3 3 3 2 5 3 ...
## $ dosis : num [1:515] 3 3 4 3 2 2 2 1 4 3 ...
## $ razon_nv : Factor w/ 7 levels "Razón 1","Razón 10",..: 4 5 1 5 5 5 5 5 1 5 ...
## $ periodico : Factor w/ 2 levels "No","Sí": 2 1 1 2 1 2 1 1 2 1 ...
## $ television : Factor w/ 2 levels "No","Sí": 2 2 2 2 1 2 2 2 2 1 ...
## $ redes_sociales : Factor w/ 2 levels "No","Sí": 1 2 2 1 2 1 2 2 1 2 ...
## $ personal_salud : Factor w/ 2 levels "No","Sí": 1 1 1 1 1 1 1 1 1 1 ...
## $ radio : Factor w/ 2 levels "No","Sí": 2 1 2 1 1 2 1 1 2 1 ...
## $ paginas_internet : Factor w/ 2 levels "No","Sí": 1 1 2 2 1 1 1 1 1 2 ...
## $ escuela : Factor w/ 2 levels "No","Sí": 2 1 1 1 1 1 1 1 1 1 ...
## $ mensajes : Factor w/ 3 levels "No","No recuerda",..: 3 3 3 3 3 3 3 3 3 3 ...
## $ patrocinio : Factor w/ 5 levels "Asociación Salvadoreña Promotora de la Salud (ASPS)",..: 5 1 4 2 2 2 1 2 1 2 ...
## $ uso_de_mascarilla : Factor w/ 2 levels "No","Sí": 2 2 2 2 1 1 1 1 2 2 ...
## $ distanciamiento_social : Factor w/ 2 levels "No","Sí": 2 1 2 2 2 1 2 1 2 1 ...
## $ lavado_de_manos : Factor w/ 2 levels "No","Sí": 1 2 2 1 2 1 2 1 2 2 ...
## $ ponerse_la_vacuna : Factor w/ 2 levels "No","Si": 2 1 1 2 2 1 1 1 1 2 ...
## $ no_recuerdo : Factor w/ 2 levels "No","Si": 1 1 1 1 1 1 1 2 1 1 ...
## $ todas : Factor w/ 2 levels "No","Sí": 1 1 1 1 1 2 1 1 1 1 ...
## $ No_he_escuchado : Factor w/ 2 levels "No","Sí": 1 1 1 1 1 1 1 1 1 1 ...
## $ transmite_por_el_agua : Factor w/ 2 levels "No","Si": 2 1 1 2 1 2 1 2 2 1 ...
## $ transmite_en_las_suelas: Factor w/ 2 levels "No","Sí": 2 1 1 2 1 2 1 2 2 1 ...
## $ rociar_desinfectantes : Factor w/ 2 levels "No","Sí": 2 1 2 2 1 2 1 2 2 1 ...
## $ beben_alcohol : Factor w/ 2 levels "No","Sí": 1 1 1 2 1 1 1 1 1 1 ...
## $ pueden_dejar_de_aplicar: Factor w/ 2 levels "No","Sí": 2 1 1 1 1 1 1 2 1 1 ...
## $ no_se_debe_vacunar : Factor w/ 2 levels "No","Sí": 1 1 2 2 2 1 2 1 1 2 ...
## $ producen_esterilidad : Factor w/ 2 levels "No","Sí": 1 1 1 1 1 1 2 1 1 1 ...
## $ producen_homosexualidad: Factor w/ 2 levels "No","Sí": 1 2 1 1 1 1 1 1 1 1 ...
## $ inyectan_el_virus : Factor w/ 2 levels "No","Sí": 1 1 2 2 1 2 1 1 1 1 ...
## $ antibioticos_son_buenos: Factor w/ 2 levels "No","Sí": 1 1 1 2 1 2 1 2 2 1 ...
## $ vitaminas_y_minerales : Factor w/ 2 levels "No","Sí": 1 1 1 1 1 1 1 2 2 1 ...
## $ entrevistadoras : num [1:515] 2 1 2 2 1 2 1 2 2 1 ...
## $ puntaje_A : num [1:515] 17 19 25 21 19 16 20 13 17 22 ...
## $ c1recod : num [1:515] 0 1 1 1 1 1 1 1 1 1 ...
## $ c2recod : num [1:515] 0 1 1 1 1 1 1 1 1 1 ...
## $ c3recod : num [1:515] 0 1 0 1 1 0 1 0 0 1 ...
## $ c4recod : num [1:515] 1 1 1 1 1 1 1 0 0 1 ...
## $ c5recod : num [1:515] 1 0 1 1 0 1 0 0 0 0 ...
## $ c6recod : num [1:515] 1 1 0 1 1 0 1 0 0 1 ...
## $ c7recod : num [1:515] 0 0 0 0 0 1 1 0 1 1 ...
## $ c8recod : num [1:515] 1 1 1 1 1 1 1 1 1 1 ...
## $ c9recod : num [1:515] 1 1 0 1 1 1 1 1 1 1 ...
## $ c10recod : num [1:515] 0 1 1 0 1 1 1 1 1 1 ...
## $ puntaje_C : num [1:515] 5 8 6 8 8 8 9 5 6 9 ...
## $ puntaje_P : num [1:515] 20 5 18 16 5 15 7 12 15 6 ...
Una distribución de frecuencias nos muestra cuántas veces ocurre cada valor de una variable en nuestro conjunto de datos.
Es el número de veces que aparece un determinado valor. Usamos la
función table() para calcularla.
# Frecuencia absoluta para la variable 'nivel_edu'
frec_abs <- table(datos$nivel_edu)
print(frec_abs)##
## Bachillerato Nunca asistió Primer ciclo Segundo ciclo Técnico
## 185 22 48 81 20
## Tercer ciclo Universitario
## 117 42
Para crear una tabla más limpia y con encabezados personalizados
podemos utilizar la función kabledel paquete
knitr
# 1. Crear la tabla de frecuencias como antes
frec_abs <- table(datos$nivel_edu)
# 2. Convertir el objeto 'table' a un dataframe para que kable() lo maneje mejor
tabla_frec_df <- as.data.frame(frec_abs)
# 3. Usar kable() para presentar la tabla
knitr::kable(
tabla_frec_df,
# 4. (Opcional pero recomendado) Personalizar los nombres de las columnas
col.names = c("Nivel Educativo", "Frecuencia Absoluta"),
# 5. (Opcional) Añadir un título a la tabla
caption = "Distribucion de Frecuencias del Nivel Educativo"
)| Nivel Educativo | Frecuencia Absoluta |
|---|---|
| Bachillerato | 185 |
| Nunca asistió | 22 |
| Primer ciclo | 48 |
| Segundo ciclo | 81 |
| Técnico | 20 |
| Tercer ciclo | 117 |
| Universitario | 42 |
Es la proporción de veces que aparece cada valor. Se calcula
dividiendo la frecuencia absoluta por el total de datos. Usamos
prop.table().
##
## Bachillerato Nunca asistió Primer ciclo Segundo ciclo Técnico
## 0.35922330 0.04271845 0.09320388 0.15728155 0.03883495
## Tercer ciclo Universitario
## 0.22718447 0.08155340
##
## Bachillerato Nunca asistió Primer ciclo Segundo ciclo Técnico
## 35.922330 4.271845 9.320388 15.728155 3.883495
## Tercer ciclo Universitario
## 22.718447 8.155340
Con el siguiente código calcularemos las frecuencias absolutas, luego las usaremos para obtener las relativas y porcentuales, y finalmente presentaremos todo en una tabla bien formateada.
# Usando dplyr para calcular todas las frecuencias en un solo flujo
tabla_relativa <- datos %>%
count(nivel_edu, name = "Frecuencia_Absoluta") %>% # Cuenta las frecuencias absolutas para 'nivel_edu'
mutate(
Frecuencia_Relativa = Frecuencia_Absoluta / sum(Frecuencia_Absoluta),
Porcentaje = Frecuencia_Relativa * 100
) # Calcula las frecuencias relativas y porcentuales
kable(
tabla_relativa,# Presentar la tabla final con kable()
col.names = c("Nivel Educativo", "Frec. Absoluta", "Frec. Relativa", "Porcentaje (%)"),# Personalizar los nombres de las columnas para la presentación
caption = "Distribucion de Frecuencias Relativas y Porcentuales del Nivel Educativo", # Añadir un título a la tabla
digits = c(0, 0, 2, 1) # 0 decimales para Frec. Absoluta, 2 para Relativa, 1 para Porcentaje
)| Nivel Educativo | Frec. Absoluta | Frec. Relativa | Porcentaje (%) |
|---|---|---|---|
| Bachillerato | 185 | 0.36 | 35.9 |
| Nunca asistió | 22 | 0.04 | 4.3 |
| Primer ciclo | 48 | 0.09 | 9.3 |
| Segundo ciclo | 81 | 0.16 | 15.7 |
| Técnico | 20 | 0.04 | 3.9 |
| Tercer ciclo | 117 | 0.23 | 22.7 |
| Universitario | 42 | 0.08 | 8.2 |
Es la suma de las frecuencias relativas de los valores menores o
iguales al valor actual. Usamos cumsum() sobre la
frecuencia relativa.
## Bachillerato Nunca asistió Primer ciclo Segundo ciclo Técnico
## 0.3592233 0.4019417 0.4951456 0.6524272 0.6912621
## Tercer ciclo Universitario
## 0.9184466 1.0000000
Podemos unir todo en una sola tabla para una mejor visualización.
# Unimos todo en un data.frame
tabla_frecuencias <- as.data.frame(frec_abs)
names(tabla_frecuencias) <- c("Nivel_Educativo", "Frec_Absoluta")
tabla_frecuencias <- tabla_frecuencias %>%
mutate(
Frec_Relativa = prop.table(Frec_Absoluta),
Porcentaje = Frec_Relativa * 100,
Frec_Acumulada = cumsum(Frec_Relativa),
Porecntaje_Acum = Frec_Acumulada * 100
)
# Mostramos la tabla con kable() para un formato limpio
kable(tabla_frecuencias,
caption = "Tabla de Frecuencias para Nivel Educativo",
digits = 2) # Redondeamos a 2 decimales| Nivel_Educativo | Frec_Absoluta | Frec_Relativa | Porcentaje | Frec_Acumulada | Porecntaje_Acum |
|---|---|---|---|---|---|
| Bachillerato | 185 | 0.36 | 35.92 | 0.36 | 35.92 |
| Nunca asistió | 22 | 0.04 | 4.27 | 0.40 | 40.19 |
| Primer ciclo | 48 | 0.09 | 9.32 | 0.50 | 49.51 |
| Segundo ciclo | 81 | 0.16 | 15.73 | 0.65 | 65.24 |
| Técnico | 20 | 0.04 | 3.88 | 0.69 | 69.13 |
| Tercer ciclo | 117 | 0.23 | 22.72 | 0.92 | 91.84 |
| Universitario | 42 | 0.08 | 8.16 | 1.00 | 100.00 |
Las tablas de contingencia o tabulaciones cruzadas nos permiten analizar la relación entre dos o más variables categóricas.
Crear una tabla cruzada de genero vrs enfcro con la función
table(), el formato es table(filas, columnas). Para que el
género esté en las columnas lo pondremos como segundo argumento.
# Crea la tabla de contingencia.
# La primera variable (enf_cro) va en las filas, la segunda (genero) en las columnas.
tabla_cruzada <- table(datos$enf_cro, datos$genero)
# Muestra la tabla con kable() para una presentación limpia
knitr::kable(
tabla_cruzada,
caption = "Tabla de Contingencia: Padecimiento de Enfermedad Crónica vs. Género"
)| Femenino | Masculino | |
|---|---|---|
| No | 210 | 136 |
| No sabe | 1 | 2 |
| Sí | 80 | 86 |
Esta tabla te muestra el conteo absoluto de cuántas personas caen en cada combinación de las categorías (ej. cuántos hombres tienen una enfermedad crónica).
A menudo es más útil ver las proporciones o porcentajes. Puedes calcularlos fácilmente con la función prop.table().
Esto responde a la pregunta: “Del total de personas que SÍ padecen una enfermedad crónica, ¿qué porcentaje son hombres y qué porcentaje son mujeres?”.
# Crear la tabla de frecuencias absolutas
tabla_cruzada_percent <- table(datos$enf_cro, datos$genero)
# Calcular los porcentajes por fila (margin = 1) y redondear
# Multiplicamos por 100 para obtener el porcentaje.
tabla_porcentajes_fila <- round(prop.table(tabla_cruzada, margin = 1) * 100, 1)
# Mostrar la tabla de porcentajes con kable()
knitr::kable(
tabla_porcentajes_fila,
caption = "Distribución Porcentual por Fila: Enfermedad Crónica vs. Género (%)"
)| Femenino | Masculino | |
|---|---|---|
| No | 60.7 | 39.3 |
| No sabe | 33.3 | 66.7 |
| Sí | 48.2 | 51.8 |
Para calcular porcentajes por columna, simplemente cambia el argumento a margin = 2. Esto respondería a la pregunta: “Del total de hombres, ¿qué porcentaje padece una enfermedad crónica?”.
Primero, vamos a categorizar las variables de puntajes en tres niveles: “Bajo” (<6), “Medio” (6 a 8), y “Alto” (>8). Luego calcularemos el promedio de dosis de vacuna para cada categoría.
# Categorizar los puntajes usando la función cut()
datos <- datos %>%
mutate(across(
.cols = c(puntaje_C, puntaje_A, puntaje_P),
.fns = ~ cut(
.x,
breaks = quantile(.x, probs = c(0, 0.25, 0.75, 1), na.rm = TRUE),
labels = c("Bajo", "Medio", "Alto"),
include.lowest = TRUE,
ordered_result = TRUE
),
.names = "cat_{.col}" # Crea nuevas columnas: cat_puntaje_C, cat_puntaje_A, etc.
))
# --- Verificación ---
# Veamos cómo quedaron distribuidas las nuevas categorías para 'puntaje_C'
# (Notarás que 'Bajo' tiene aprox. el 50% de los datos)
tabla_verificacion <- table(datos$cat_puntaje_C)
kable(tabla_verificacion, col.names = c("Categoría de Conocimiento", "Frecuencia"))| Categoría de Conocimiento | Frecuencia |
|---|---|
| Bajo | 174 |
| Medio | 321 |
| Alto | 20 |
# Calcular el promedio de dosis para cada categoría de puntaje de CONOCIMIENTOS
promedio_dosis_C <- datos %>%
group_by(cat_puntaje_C) %>%
summarise(Promedio_Dosis = mean(dosis, na.rm = TRUE))
kable(promedio_dosis_C,
caption = "Promedio de Dosis de Vacuna por Nivel de Conocimiento",
digits = 2)| cat_puntaje_C | Promedio_Dosis |
|---|---|
| Bajo | 2.29 |
| Medio | 2.44 |
| Alto | 1.60 |
# Podemos hacer lo mismo para Actitudes y Prácticas
promedio_dosis_A <- datos %>% group_by(cat_puntaje_A) %>% summarise(Promedio_Dosis = mean(dosis, na.rm = TRUE))
promedio_dosis_P <- datos %>% group_by(cat_puntaje_P) %>% summarise(Promedio_Dosis = mean(dosis, na.rm = TRUE))
kable(promedio_dosis_A, caption = "Promedio de Dosis de Vacuna por Nivel de Actitud", digits = 2)| cat_puntaje_A | Promedio_Dosis |
|---|---|
| Bajo | 1.87 |
| Medio | 2.38 |
| Alto | 2.95 |
| cat_puntaje_P | Promedio_Dosis |
|---|---|
| Bajo | 2.26 |
| Medio | 2.23 |
| Alto | 2.71 |
str(datos$mensajes)
# Dicotomizar la variable 'mensajes' en "Sí = Sí" y "No = No/No recuerda".
datos <- datos %>%
mutate(
mensajes_dicot = factor(
ifelse(mensajes == "Sí", "Sí", "No/No recuerda")
)
)
# --- Verificación ---
# Esta tabla cruzada te mostrará de la variable mensajes dicotomizada.
kable(
table(
`Original (mensajes)` = datos$mensajes,
`Nueva (mensajes_dicot)` = datos$mensajes_dicot
),
caption = "Verificación de la Recodificación"
)| No/No recuerda | Sí | |
|---|---|---|
| No | 182 | 0 |
| No recuerda | 92 | 0 |
| Sí | 0 | 241 |
##
## No/No recuerda Sí
## 274 241
# Calcular el promedio de puntajes para cada categoría de 'mensajes_dic'
promedio_puntajes <- datos %>%
group_by(mensajes_dicot) %>%
summarise(
Promedio_Conocimiento = mean(puntaje_C, na.rm = TRUE),
Promedio_Actitud = mean(puntaje_A, na.rm = TRUE),
Promedio_Practica = mean(puntaje_P, na.rm = TRUE)
)
kable(promedio_puntajes,
caption = "Promedio de Puntajes según Exposición a Mensajes educativos",
digits = 2)| mensajes_dicot | Promedio_Conocimiento | Promedio_Actitud | Promedio_Practica |
|---|---|---|---|
| No/No recuerda | 7.43 | 16.08 | 9.26 |
| Sí | 6.79 | 17.68 | 14.28 |
Ahora, vamos a identificar el promedio de conocimientos según exposición a mensajes educativos en los últimos 3 meses.
# Calcular el promedio de puntajes para cada categoría de 'mensajes_dicot'
promedio_puntajes <- datos %>%
group_by(mensajes_dicot) %>%
summarise(
Promedio_Conocimiento = mean(puntaje_C, na.rm = TRUE),
Promedio_Actitud = mean(puntaje_A, na.rm = TRUE),
Promedio_Practica = mean(puntaje_P, na.rm = TRUE)
)
kable(promedio_puntajes,
caption = "Promedio de Puntajes según Recepción de Mensajes",
digits = 2)| mensajes_dicot | Promedio_Conocimiento | Promedio_Actitud | Promedio_Practica |
|---|---|---|---|
| No/No recuerda | 7.43 | 16.08 | 9.26 |
| Sí | 6.79 | 17.68 | 14.28 |
Las gráficas son una herramienta poderosa para entender patrones y
relaciones en los datos. Usaremos el paquete ggplot2.
Ideal para visualizar la frecuencia de variables categóricas.
# Opciones globales para los chunks de código
ggplot(datos, aes(x = area, fill = genero)) +
geom_bar(position = "dodge") +
labs(title = "Distribución de Participantes por Área de Residencia y Género",
x = "Área de Residencia",
y = "Frecuencia") +
theme_minimal()
## Histograma Muestra la distribución de una variable numérica
continua.
# Opciones globales para los chunks de código
ggplot(datos, aes(x = edad)) +
geom_histogram(binwidth = 5, fill = "skyblue", color = "black") +
labs(title = "Distribución de Edades",
x = "Edad (años)",
y = "Frecuencia") +
theme_minimal()Similar al histograma, pero usa líneas en lugar de barras. Podemos superponerlo.
ggplot(datos, aes(x = edad, color = genero)) +
geom_freqpoly(binwidth = 5) +
labs(title = "Distribución de Edades por Género",
x = "Edad (años)",
y = "Frecuencia") +
theme_minimal()Útil para visualizar la distribución de una variable numérica para diferentes categorías.
ggplot(datos, aes(x = nivel_edu, y = puntaje_C, fill = nivel_edu)) +
geom_dotplot(binaxis = "y", stackdir = "center", dotsize = 0.8) +
labs(title = "Puntaje de Conocimientos por Nivel Educativo",
x = "Nivel Educativo",
y = "Puntaje de Conocimientos") +
theme_minimal() +
theme(legend.position = "none") # Ocultamos la leyenda porque es redundanteExcelente para comparar distribuciones de una variable numérica entre varios grupos.
ggplot(datos, aes(x = nivel_edu, y = puntaje_A, fill = nivel_edu)) +
geom_boxplot() +
labs(title = "Distribución del Puntaje de Actitudes por Nivel Educativo",
x = "Nivel Educativo",
y = "Puntaje de Actitudes") +
theme_minimal() +
theme(legend.position = "none")Muestra la relación entre dos variables numéricas.
ggplot(datos, aes(x = puntaje_A, y = puntaje_P)) +
geom_point(aes(color = area), alpha = 0.7) +
geom_smooth(method = "lm", color = "red", se = FALSE) + # Añade una línea de tendencia
labs(title = "Relación entre Puntaje de Actitudes y Prácticas",
x = "Puntaje de Actitudes",
y = "Puntaje de Prácticas") +
theme_minimal()Es ideal para mostrar la evolución de una variable a lo largo del tiempo. Como no tenemos una variable de tiempo, crearemos un ejemplo simple que muestre el promedio de edad por número de dosis.
# Calcular el promedio de edad para cada número de dosis
datos_linea <- datos %>%
group_by(dosis) %>%
summarise(Edad_Promedio = mean(edad, na.rm = TRUE))
ggplot(datos_linea, aes(x = dosis, y = Edad_Promedio)) +
geom_line(color = "navy") +
geom_point(color = "navy", size = 3) +
labs(title = "Edad Promedio según Dosis de Vacuna Recibidas",
x = "Número de Dosis",
y = "Edad Promedio (años)") +
theme_minimal()Comparemos el puntaje de conocimientos según si las personas fueron
expuestas a mensajes educativos o no (variable
mensajes_dicot)
# Crear los histogramas comparativos
# Mapeamos la variable puntaje_C al eje x.Usamos facet_wrap(~ mensajes_recod, ncol = 1) para crear un histograma para cada categoría de la variable mensajes_recod y apilarlos uno debajo del otro.
ggplot(datos, aes(x = puntaje_C)) +
geom_histogram(binwidth = 1, fill = "steelblue", color = "white", alpha = 0.8) +
facet_wrap(~ mensajes_dicot, ncol = 1) +
labs(
title = "Comparación de la Distribución del Puntaje de Conocimientos",
subtitle = "Según si el participante escuchó o no mensajes educativos",
x = "Puntaje de Conocimientos (puntaje_C)",
y = "Frecuencia (Conteo)"
) +
theme_bw() # Usamos un tema diferente para variarAhora cambiemos por un gráfico de cajas
# Mapear las variables a los ejes
# - x: La variable categórica para los grupos (mensajes_recod).
# - y: La variable numérica cuya distribución queremos ver (puntaje_C).
# - fill: Coloreamos las cajas según el grupo para mejorar la estética.
ggplot(datos, aes(x = mensajes_dicot, y = puntaje_C, fill = mensajes_dicot)) +
geom_boxplot(alpha = 0.7) + # 2. Añadir la geometría del boxplot
#geom_jitter(width = 0.2, alpha = 0.4) + # (Opcional) Añadir los puntos de datos reales con
#algo de dispersión (jitter). Esto ayuda a ver la
#distribución real de los datos.
labs(
title = "Comparación del Puntaje de Conocimientos",
subtitle = "Según si el participante recibió o no mensajes educativos",
x = "Recibió Mensajes Educativos",
y = "Puntaje de Conocimientos"
) + # Añadir etiquetas y títulos claros
theme_minimal() +
theme(legend.position = "none") # Aplicar un tema y remover la leyenda (es redundante)Reunidos en grupos, deberán elaborar la presentación de resultados del estudio Conocimientos, Actitudes y Prácticas hacia las medidas preventivas de COVID-19, siguiendo el protocolo del estudio que les fue compartido. El análisis descriptivo deberá contener una tabla, una gráfica y un párrafo describiendo los datos.