Sesión 4

Taller de Visualizaciones y Creación de Dashboards para las Ciencias Sociales

Author

Noam López Villanes

1

# Cada library() activa funciones que usaremos en los siguientes pasos.
library(ggplot2)
# Cada library() activa funciones que usaremos en los siguientes pasos.
library(dplyr)
library(haven)

Este paso prepara el entorno de trabajo y evita errores por funciones no disponibles. Conviene ejecutarlo al inicio para asegurar un flujo reproducible.

2

# Importamos el archivo SPSS como punto de partida del análisis.
datos <- read_sav("encuesta_electoral_peru_2026.sav")
# Encadenamos operaciones con %>% para leer el proceso paso a paso.
datos <- datos %>%
# mutate() crea o modifica variables dentro del data frame.
  mutate(
    candidato_fct = as_factor(candidato_intencion),
    region_fct = as_factor(region),
    genero_fct = as_factor(genero),
    educacion_fct = as_factor(nivel_educativo),
    aprobacion_fct = as_factor(aprob_gobierno)
  )

# glimpse() resume la estructura de la base y los tipos de variables.
glimpse(datos)
Rows: 2,500
Columns: 14
$ id_encuestado       <dbl> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,…
$ edad                <dbl> 48, 24, 42, 39, 30, 24, 29, 25, 42, 33, 34, 29, 37…
$ ingreso_mensual     <dbl> 1025, 1520, 2050, 1940, 1025, 1025, 1025, 1410, 13…
$ candidato_intencion <dbl+lbl> 4, 1, 3, 7, 2, 5, 2, 7, 7, 7, 7, 3, 7, 4, 1, 7…
$ region              <dbl+lbl> 2, 4, 3, 1, 4, 4, 4, 2, 3, 1, 1, 4, 1, 3, 3, 2…
$ genero              <dbl+lbl> 2, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 2, 1, 1, 1, 1…
$ nivel_educativo     <dbl+lbl> 4, 2, 3, 3, 4, 2, 4, 4, 4, 3, 3, 3, 3, 2, 3, 3…
$ aprob_gobierno      <dbl+lbl> 1, 1, 4, 3, 2, 1, 1, 1, 4, 1, 1, 2, 1, 1, 5, 1…
$ interes_politico    <dbl+lbl> 1, 2, 3, 1, 3, 1, 1, 3, 2, 1, 2, 1, 3, 1, 1, 1…
$ candidato_fct       <fct> Candidato D, Candidato A, Candidato C, Blanco/Vici…
$ region_fct          <fct> Costa Norte, Sierra, Costa Sur, Lima Metropolitana…
$ genero_fct          <fct> Mujer, Hombre, Hombre, Hombre, Mujer, Hombre, Muje…
$ educacion_fct       <fct> Superior Universitaria, Secundaria, Superior Técni…
$ aprobacion_fct      <fct> Muy en desacuerdo, Muy en desacuerdo, De acuerdo, …

Aquí se importan los datos y se convierten variables clave en factores legibles. Esta transformación facilita tanto la interpretación como la construcción de gráficos categóricos.

3

datos <- datos_base

datos %>%
  group_by(candidato_fct) %>%
# summarise() resume la información en una salida más compacta.
  summarise(n = n()) %>%
# arrange() ordena los resultados para facilitar la lectura.
  arrange(desc(n)) %>%
# gt::gt() presenta la salida en un formato tabular más limpio.
  gt::gt()
Intención de voto presidencial 2026 n
Blanco/Viciado 1274
Candidato A 290
Candidato B 241
Candidato C 215
Candidato D 208
Candidato F 146
Candidato E 126

Esta tabla resume la distribución absoluta de la intención de voto. Es útil como primer vistazo porque permite identificar liderazgos, rezagos y categorías dominantes antes de graficar.

4

datos <- datos_base
# Definimos el objeto gráfico y las variables que se mapearán a la visualización.
p <- ggplot(datos, aes(x = candidato_fct))
p <- p + geom_bar(fill = "steelblue")
p + theme_minimal()

El gráfico de barras es apropiado para comparar cantidades entre categorías discretas. Su principal ventaja es que permite reconocer diferencias de magnitud de manera inmediata.

5

datos <- datos_base
# Definimos el objeto gráfico y las variables que se mapearán a la visualización.
p <- ggplot(datos, aes(x = candidato_fct)) +
# geom_bar() dibuja barras para comparar frecuencias o conteos.
  geom_bar(fill = "darkblue") +
# labs() define títulos, ejes y leyendas.
  labs(title = "Intención de voto general") +
# Elegimos un tema para simplificar la presentación del gráfico.
  theme_minimal()
p <- p + coord_flip()
p

La rotación del eje mejora la lectura cuando las etiquetas son largas o numerosas. Es una solución sencilla y muy útil en tableros y reportes ejecutivos.

6

datos <- datos_base
segunda_variable <- datos$candidato_fct
segunda_variable <- datos$candidato_fct
tabla_region <- table(datos$region_fct, segunda_variable)

# Convertimos la tabla cruzada en un formato más fácil de presentar.
as.data.frame.matrix(tabla_region) %>%
# Pasamos los nombres de fila a una columna explícita.
  tibble::rownames_to_column("Región") %>%
# gt::gt() presenta la salida en un formato tabular más limpio.
  gt::gt()
Región Candidato A Candidato B Candidato C Candidato D Candidato E Candidato F Blanco/Viciado
Lima Metropolitana 102 86 72 68 51 44 450
Costa Norte 56 52 32 38 23 27 245
Costa Sur 32 23 27 13 12 18 123
Sierra 72 51 56 70 27 35 327
Selva 28 29 28 19 13 22 129

Esta tabla cruzada muestra el detalle exacto del cruce entre región y candidato. Resulta especialmente valiosa cuando interesa revisar cifras puntuales antes de pasar a una visualización.

7

datos <- datos_base
mapeo <- aes(x = candidato_fct)
mapeo <- aes(x = candidato_fct, fill = region_fct)
# Definimos el objeto gráfico y las variables que se mapearán a la visualización.
ggplot(datos, mapeo) +
# geom_bar() dibuja barras para comparar frecuencias o conteos.
  geom_bar(position = "dodge") +
# coord_flip() gira los ejes para mejorar la lectura de etiquetas largas.
  coord_flip() +
# Elegimos un tema para simplificar la presentación del gráfico.
  theme_minimal() +
# labs() define títulos, ejes y leyendas.
  labs(title = "Intención de voto por candidato y región")

Las barras agrupadas sirven para comparar conteos absolutos entre categorías y subgrupos al mismo tiempo. Funcionan bien cuando importa ver diferencias de volumen, no solo proporciones.

8

datos <- datos_base

# Definimos el objeto gráfico y las variables que se mapearán a la visualización.
ggplot(datos, aes(x = candidato_fct, fill = region_fct)) +
geom_bar(position = "fill") +
# Ajustamos la escala para mejorar lectura, formato o color.
  scale_y_continuous(labels = scales::percent) +
# coord_flip() gira los ejes para mejorar la lectura de etiquetas largas.
  coord_flip() +
# Elegimos un tema para simplificar la presentación del gráfico.
  theme_bw() +
# labs() define títulos, ejes y leyendas.
  labs(
    title = "Composición regional dentro de cada candidato",
    y = "Proporción regional por candidato"
  )

Este formato estandariza todas las barras al 100%, por lo que facilita comparar composiciones internas. Es recomendable cuando los tamaños totales son distintos entre categorías.

9

datos <- datos_base

# Definimos el objeto gráfico y las variables que se mapearán a la visualización.
ggplot(datos, aes(x = edad)) +
  geom_histogram(bins = 20, fill="tomato", color="black") +
# Elegimos un tema para simplificar la presentación del gráfico.
  theme_classic() +
# labs() define títulos, ejes y leyendas.
  labs(
    title = "Histograma de la edad del electorado",
    x = "Edad del encuestado (años)",
    y = "Frecuencia"
  )

El histograma permite evaluar la forma general de una variable continua: concentración, dispersión, asimetría y posibles acumulaciones. Es una herramienta básica para explorar distribuciones.

10

datos <- datos_base

# Definimos el objeto gráfico y las variables que se mapearán a la visualización.
ggplot(datos, aes(x = edad)) +
geom_density(fill="lightblue", alpha=0.6) +
# Elegimos un tema para simplificar la presentación del gráfico.
  theme_minimal() +
# labs() define títulos, ejes y leyendas.
  labs(
    title = "Densidad de la edad del electorado",
    x = "Edad del encuestado (años)",
    y = "Densidad relativa"
  )

La curva de densidad ofrece una lectura más suave que el histograma y ayuda a detectar patrones globales. Es útil cuando se quiere enfatizar la forma de la distribución más que los conteos exactos.

11

datos <- datos_base

# Definimos el objeto gráfico y las variables que se mapearán a la visualización.
ggplot(datos, aes(x = candidato_fct, y = edad)) +
geom_boxplot(fill = "lightgreen") +
# coord_flip() gira los ejes para mejorar la lectura de etiquetas largas.
  coord_flip() +
# Elegimos un tema para simplificar la presentación del gráfico.
  theme_light() +
# labs() define títulos, ejes y leyendas.
  labs(
    title = "Distribución de edad por candidato",
    x = "Intención de voto presidencial 2026",
    y = "Edad del encuestado (años)"
  )

El boxplot resume mediana, rango intercuartil, dispersión y valores atípicos. Es muy conveniente para comparar rápidamente distribuciones numéricas entre grupos.

12

datos <- datos_base

# Definimos el objeto gráfico y las variables que se mapearán a la visualización.
ggplot(datos, aes(x = candidato_fct, y = edad)) +
geom_violin(fill = "purple", alpha = 1) +
# coord_flip() gira los ejes para mejorar la lectura de etiquetas largas.
  coord_flip() +
# Elegimos un tema para simplificar la presentación del gráfico.
  theme_minimal() +
# labs() define títulos, ejes y leyendas.
  labs(
    title = "Densidad de edad por candidato",
    x = "Intención de voto presidencial 2026",
    y = "Edad del encuestado (años)"
  )

El gráfico de violín conserva la comparación por grupos y, además, muestra dónde se concentra la densidad. Es especialmente útil cuando interesa ver la forma interna de cada distribución.

13

datos <- datos_base
# Encadenamos operaciones con %>% para leer el proceso paso a paso.
datos_mujeres <- datos %>%
filter(genero == 2) %>%
# select() nos deja solo las variables necesarias para este paso.
  select(candidato_fct, edad, genero)
  
# dim() devuelve el número de filas y columnas del objeto.
dim(datos_mujeres)
[1] 1236    3
datos_mujeres %>%
# count() calcula frecuencias por categoría.
  count(candidato_fct) %>%
# gt::gt() presenta la salida en un formato tabular más limpio.
  gt::gt()
Intención de voto presidencial 2026 n
Candidato A 142
Candidato B 130
Candidato C 95
Candidato D 95
Candidato E 66
Candidato F 76
Blanco/Viciado 632

Filtrar una subpoblación permite concentrar el análisis en un segmento específico. Esta estrategia es clave cuando el interés está en patrones diferenciados dentro del conjunto total.

14

datos <- datos_base
# Definimos el objeto gráfico y las variables que se mapearán a la visualización.
p <- ggplot(datos, aes(x = candidato_fct)) +
# geom_bar() dibuja barras para comparar frecuencias o conteos.
  geom_bar(fill="darkgray") +
# coord_flip() gira los ejes para mejorar la lectura de etiquetas largas.
  coord_flip() +
# Elegimos un tema para simplificar la presentación del gráfico.
  theme_minimal()
p <- p + facet_wrap(~genero_fct)
p +
# labs() define títulos, ejes y leyendas.
  labs(
    title = "Intención de voto por género",
    x = "Intención de voto presidencial 2026",
    y = "Número de encuestados"
  )

Las facetas separan la información en paneles comparables sin superponer categorías. Son muy útiles para contrastar subgrupos manteniendo la misma escala visual.

15

datos <- datos_base

# Definimos el objeto gráfico y las variables que se mapearán a la visualización.
ggplot(datos, aes(x = edad, y = ingreso_mensual)) +
geom_point() +
# Ajustamos la escala para mejorar lectura, formato o color.
  scale_y_log10(labels=scales::comma) +
# Elegimos un tema para simplificar la presentación del gráfico.
  theme_bw() +
# labs() define títulos, ejes y leyendas.
  labs(
    title = "Ingreso mensual según edad",
    x = "Edad del encuestado (años)",
    y = "Ingreso mensual estimado del hogar (S/.)"
  )

El diagrama de dispersión es la opción natural para examinar dos variables continuas. Permite evaluar asociación, dispersión, concentraciones y posibles valores extremos.

16

datos <- datos_base

# Definimos el objeto gráfico y las variables que se mapearán a la visualización.
ggplot(datos, aes(x = edad, y = ingreso_mensual)) +
geom_point(alpha = 0.2, color = "darkred") +
# Ajustamos la escala para mejorar lectura, formato o color.
  scale_y_log10(labels=scales::comma) +
# Elegimos un tema para simplificar la presentación del gráfico.
  theme_bw() +
# labs() define títulos, ejes y leyendas.
  labs(
    title = "Ingreso mensual según edad con transparencia",
    x = "Edad del encuestado (años)",
    y = "Ingreso mensual estimado del hogar (S/.)"
  )

La transparencia ayuda a resolver el sobreapilamiento de puntos. Gracias a ello, las zonas más densas se distinguen mejor y la lectura del patrón general mejora.

17

datos <- datos_base
mapeo <- aes(x = edad, y = ingreso_mensual)
mapeo <- aes(x = edad, y = ingreso_mensual, color = genero_fct)
# Definimos el objeto gráfico y las variables que se mapearán a la visualización.
ggplot(datos, mapeo) +
# geom_point() representa observaciones individuales en un plano XY.
  geom_point(alpha = 0.4) +
# Ajustamos la escala para mejorar lectura, formato o color.
  scale_y_log10(labels = scales::comma) +
# Elegimos un tema para simplificar la presentación del gráfico.
  theme_minimal() +
# labs() define títulos, ejes y leyendas.
  labs(
    title = "Ingreso mensual según edad y género",
    x = "Edad del encuestado (años)",
    y = "Ingreso mensual estimado del hogar (S/.)",
    color = "Género del encuestado"
  )

Incorporar color agrega una tercera dimensión de análisis sin perder el plano principal. Esta técnica es útil para detectar si la relación entre dos variables cambia según un grupo.

18

datos <- datos_base

# Definimos el objeto gráfico y las variables que se mapearán a la visualización.
ggplot(datos, aes(x = candidato_fct, y = ingreso_mensual)) +
geom_jitter(alpha = 0.3, width = 0.2, color="brown") +
# Ajustamos la escala para mejorar lectura, formato o color.
  scale_y_log10(labels=scales::comma) +
# coord_flip() gira los ejes para mejorar la lectura de etiquetas largas.
  coord_flip() +
# Elegimos un tema para simplificar la presentación del gráfico.
  theme_minimal() +
# labs() define títulos, ejes y leyendas.
  labs(
    title = "Ingreso mensual por candidato",
    x = "Intención de voto presidencial 2026",
    y = "Ingreso mensual estimado del hogar (S/.)"
  )

El jitter separa puntos que caerían uno encima de otro en variables categóricas. Es recomendable cuando se quiere mostrar variación individual sin ocultar la densidad de casos.

19

datos <- datos_base

# Definimos el objeto gráfico y las variables que se mapearán a la visualización.
ggplot(datos, aes(x = candidato_fct, y = edad)) +
# geom_jitter() separa puntos superpuestos añadiendo una leve variación visual.
  geom_jitter(alpha = 0.2, width=0.15, color="grey40") +
geom_boxplot(outlier.shape = NA, fill = NA, color = "black") +
# coord_flip() gira los ejes para mejorar la lectura de etiquetas largas.
  coord_flip() +
# Elegimos un tema para simplificar la presentación del gráfico.
  theme_bw() +
# labs() define títulos, ejes y leyendas.
  labs(
    title = "Edad por candidato: jitter y boxplot",
    x = "Intención de voto presidencial 2026",
    y = "Edad del encuestado (años)"
  )

Esta combinación une un resumen estadístico claro con la distribución observada de los datos. Es una opción sólida cuando se busca equilibrio entre precisión y riqueza visual.

20

datos <- datos_base
mapeo <- aes(x = educacion_fct)
mapeo <- aes(x = educacion_fct, fill = aprobacion_fct)
# Definimos el objeto gráfico y las variables que se mapearán a la visualización.
ggplot(datos, mapeo) +
# geom_bar() dibuja barras para comparar frecuencias o conteos.
  geom_bar(position = "fill") +
# Ajustamos la escala para mejorar lectura, formato o color.
  scale_y_continuous(labels = scales::percent) +
# Ajustamos la escala para mejorar lectura, formato o color.
  scale_fill_brewer(palette = "RdYlGn") +
# coord_flip() gira los ejes para mejorar la lectura de etiquetas largas.
  coord_flip() +
# Elegimos un tema para simplificar la presentación del gráfico.
  theme_minimal() +
# labs() define títulos, ejes y leyendas.
  labs(
    title = "Aprobación del gobierno según nivel educativo",
    x = "Nivel educativo",
    y = "Proporción",
    fill = "Aprobación"
  )

El apilado al 100% permite comparar perfiles proporcionales entre niveles educativos. Es apropiado cuando interesa la composición relativa de las respuestas más que el tamaño bruto.

21

datos <- datos_base
# Definimos el objeto gráfico y las variables que se mapearán a la visualización.
p <- ggplot(datos, aes(x = edad, fill=candidato_fct)) +
# geom_density() muestra una versión suavizada de la distribución.
  geom_density(alpha=0.5) +
# Elegimos un tema para simplificar la presentación del gráfico.
  theme_minimal() +
# theme() ajusta detalles finos de formato y jerarquía visual.
  theme(legend.position = "none")
p <- p + facet_grid(interes_politico ~ .)
p +
# labs() define títulos, ejes y leyendas.
  labs(
    title = "Edad e intención de voto según interés político",
    x = "Edad del encuestado (años)",
    y = "Densidad"
  )

Las densidades en facetas permiten comparar formas de distribución entre niveles de interés político. Son útiles para detectar si ciertos grupos presentan perfiles de edad diferenciados.

22

# Encadenamos operaciones con %>% para leer el proceso paso a paso.
datos_pastel <- datos_base %>%
# count() calcula frecuencias por categoría.
  count(genero_fct)
datos_pastel <- datos_pastel %>% mutate(fraccion = n / sum(n))

# Este control evita errores cuando aún no se ha activado la línea pedida.
if (!"fraccion" %in% names(datos_pastel)) {
# Encadenamos operaciones con %>% para leer el proceso paso a paso.
  datos_pastel <- datos_pastel %>%
    mutate(fraccion = n / sum(n))
}

# Encadenamos operaciones con %>% para leer el proceso paso a paso.
datos_pastel <- datos_pastel %>%
# mutate() crea o modifica variables dentro del data frame.
  mutate(
    ymax = cumsum(fraccion),
    ymin = c(0, head(ymax, n = -1))
  )

datos_pastel %>%
# gt::gt() presenta la salida en un formato tabular más limpio.
  gt::gt()
Género del encuestado n fraccion ymax ymin
Hombre 1264 0.5056 0.5056 0.0000
Mujer 1236 0.4944 1.0000 0.5056

Este paso construye la tabla base para una visualización circular mediante proporciones acumuladas. Es importante entenderlo porque muestra la lógica numérica detrás de la gráfica final.

23

# Encadenamos operaciones con %>% para leer el proceso paso a paso.
datos_pastel <- datos_base %>%
# count() calcula frecuencias por categoría.
  count(genero_fct) %>%
  mutate(fraccion = n / sum(n)) %>%
# mutate() crea o modifica variables dentro del data frame.
  mutate(
    ymax = cumsum(fraccion),
    ymin = c(0, head(ymax, n = -1))
  )

# Definimos el objeto gráfico y las variables que se mapearán a la visualización.
ggplot(datos_pastel, aes(ymax=ymax, ymin=ymin, xmax=4, xmin=3, fill=genero_fct)) +
# geom_rect() dibuja rectángulos que luego pueden transformarse en una dona.
  geom_rect() +
  coord_polar(theta = "y") +
  xlim(c(2, 4)) +
# Elegimos un tema para simplificar la presentación del gráfico.
  theme_void() +
# labs() define títulos, ejes y leyendas.
  labs(title="Distribución del padrón electoral por género")

La transformación polar convierte rectángulos en segmentos circulares. Conviene usar este tipo de gráfico solo cuando hay pocas categorías y el objetivo principal es mostrar composición.

24

datos <- datos_base
mapa_calor <- datos
mapa_calor <- datos %>% count(region_fct, interes_politico)

# Este control evita errores cuando aún no se ha activado la línea pedida.
if (!all(c("region_fct", "interes_politico", "n") %in% names(mapa_calor))) {
# Encadenamos operaciones con %>% para leer el proceso paso a paso.
  mapa_calor <- datos %>%
# count() calcula frecuencias por categoría.
    count(region_fct, interes_politico)
}

# Definimos el objeto gráfico y las variables que se mapearán a la visualización.
ggplot(mapa_calor, aes(x = region_fct, y = as.factor(interes_politico), fill=n)) +
# geom_tile() construye celdas rectangulares para un mapa de calor.
  geom_tile(color="white") +
# Elegimos un tema para simplificar la presentación del gráfico.
  theme_minimal() +
# labs() define títulos, ejes y leyendas.
  labs(
    title = "Mapa de calor del interés político por región",
    x = "Región",
    y = "Nivel de interés político"
  )

El mapa de calor sintetiza la intensidad de un cruce entre dos dimensiones categóricas. Es muy eficaz cuando una tabla empieza a volverse difícil de leer por el volumen de combinaciones.

25

mapa_calor <- datos_base %>%
# count() calcula frecuencias por categoría.
  count(region_fct, interes_politico)

# Definimos el objeto gráfico y las variables que se mapearán a la visualización.
ggplot(mapa_calor, aes(x = as.factor(interes_politico), y = region_fct, fill = n)) +
# geom_tile() construye celdas rectangulares para un mapa de calor.
  geom_tile(color="white") +
  scale_fill_viridis_c(option = "magma") +
# Elegimos un tema para simplificar la presentación del gráfico.
  theme_minimal() +
# labs() define títulos, ejes y leyendas.
  labs(
    title = "Mapa de calor con escala viridis",
    x = "Nivel de interés político (1 al 4)",
    y = "Región"
  )

Una buena escala cromática mejora la lectura y evita distorsiones perceptivas. Viridis suele ser una opción segura porque mantiene contraste y legibilidad.

26

mapa_calor <- datos_base %>%
# count() calcula frecuencias por categoría.
  count(region_fct, interes_politico)

# Definimos el objeto gráfico y las variables que se mapearán a la visualización.
ggplot(mapa_calor, aes(x = as.factor(interes_politico), y = region_fct, fill = n)) +
# geom_tile() construye celdas rectangulares para un mapa de calor.
  geom_tile() +
# Ajustamos la escala para mejorar lectura, formato o color.
  scale_fill_viridis_c() +
  geom_text(aes(label = n), color = "white", size=3.5) +
# Elegimos un tema para simplificar la presentación del gráfico.
  theme_light() +
# labs() define títulos, ejes y leyendas.
  labs(
    title = "Mapa de calor con etiquetas",
    x = "Nivel de interés político (1 al 4)",
    y = "Región"
  )

Las etiquetas internas aportan precisión numérica sin abandonar la representación visual. Son útiles en reportes estáticos donde el lector no puede interactuar con la figura.

27

datos <- datos_base
# Definimos el objeto gráfico y las variables que se mapearán a la visualización.
p <- ggplot(datos, aes(x = candidato_fct)) +
# geom_bar() dibuja barras para comparar frecuencias o conteos.
  geom_bar(fill="black") +
# labs() define títulos, ejes y leyendas.
  labs(title="Intención de voto con tema limpio") +
# Elegimos un tema para simplificar la presentación del gráfico.
  theme_minimal() +
# coord_flip() gira los ejes para mejorar la lectura de etiquetas largas.
  coord_flip()
# p <- p + theme(plot.title = element_text(hjust = 0.5, face = "bold"), panel.grid.minor = element_blank())
p

Ajustar el tema permite reforzar la jerarquía visual y reducir elementos distractores. Esta etapa es clave cuando el gráfico formará parte de una presentación o dashboard final.

28

datos <- datos_base
# Definimos el objeto gráfico y las variables que se mapearán a la visualización.
p <- ggplot(datos, aes(x = genero_fct, y = edad, fill = genero_fct)) +
# geom_boxplot() resume mediana, dispersión y posibles valores atípicos.
  geom_boxplot() +
# Elegimos un tema para simplificar la presentación del gráfico.
  theme_light() +
# coord_flip() gira los ejes para mejorar la lectura de etiquetas largas.
  coord_flip() +
# labs() define títulos, ejes y leyendas.
  labs(
    title = "Edad según género",
    x = "Género del encuestado",
    y = "Edad del encuestado (años)"
  )

plotly::ggplotly(p)
p

La capa interactiva agrega exploración directa sobre el gráfico, como hover y zoom. Es una buena alternativa cuando el usuario final necesita inspeccionar detalles sin salir del reporte.

29

datos <- datos_base
DT::datatable(haven::zap_labels(head(datos, 250)), options = list(pageLength = 10))
# head() permite revisar rápidamente las primeras filas del conjunto.
head(datos, 10)
# A tibble: 10 × 14
   id_encuestado  edad ingreso_mensual candidato_intencion region        genero 
           <dbl> <dbl>           <dbl> <dbl+lbl>           <dbl+lbl>     <dbl+l>
 1             1    48            1025 4 [Candidato D]     2 [Costa Nor… 2 [Muj…
 2             2    24            1520 1 [Candidato A]     4 [Sierra]    1 [Hom…
 3             3    42            2050 3 [Candidato C]     3 [Costa Sur] 1 [Hom…
 4             4    39            1940 7 [Blanco/Viciado]  1 [Lima Metr… 1 [Hom…
 5             5    30            1025 2 [Candidato B]     4 [Sierra]    2 [Muj…
 6             6    24            1025 5 [Candidato E]     4 [Sierra]    1 [Hom…
 7             7    29            1025 2 [Candidato B]     4 [Sierra]    2 [Muj…
 8             8    25            1410 7 [Blanco/Viciado]  2 [Costa Nor… 2 [Muj…
 9             9    42            1380 7 [Blanco/Viciado]  3 [Costa Sur] 2 [Muj…
10            10    33            1025 7 [Blanco/Viciado]  1 [Lima Metr… 1 [Hom…
# ℹ 8 more variables: nivel_educativo <dbl+lbl>, aprob_gobierno <dbl+lbl>,
#   interes_politico <dbl+lbl>, candidato_fct <fct>, region_fct <fct>,
#   genero_fct <fct>, educacion_fct <fct>, aprobacion_fct <fct>

Una tabla interactiva facilita filtrar, ordenar y revisar registros concretos. Resulta especialmente valiosa cuando el análisis requiere pasar del resumen al caso individual.