BIENVENIDO A LA 4ta GUÍA DE RSTUDIO PARA ESTADÍSTICA INFERENCIAL

Aquí encontrarás un ejemplo completo de la aplicación de un EDA.

1 Análisis Exploratorio de Datos

El análisis exploratorio de datos (Ver video) (EDA por sus siglas en inglés) implica el uso de gráficos y visualizaciones para explorar y analizar un conjunto de datos. El objetivo es explorar, investigar y aprender, no confirmar hipótesis estadísticas.

1.1 ¿Cuándo debo utilizarlo?

El análisis exploratorio de datos es una potente herramienta para explorar un conjunto de datos. Incluso cuando su objetivo es efectuar análisis planificados, el EDA puede utilizarse para limpiar datos, para análisis de subgrupos o simplemente para comprender mejor los datos. Un paso inicial importante en cualquier análisis de datos es representar los datos gráficamente.

No gráfico: Calcula estadísticas descriptivas de las variables

Gráfico: Calcula estadísticas de forma gráfica

Univariado: Analiza una sola variable a la vez

Multivariado: Analiza dos o más variables

A su vez, cada uno de esas dividisiones puede subdividirse según los tipos de datos con los que trabajemos: categóricos o numéricos.

1.2 Contexto:

El presente estudio se basa en una encuesta aplicada a una muestra representativa de 500 ciudadanos de la ciudad de Springfield, con el objetivo de analizar su nivel de interés en la política, la confianza en el gobierno, entre otras. Además, se examina el impacto de las redes sociales en la formación de la opinión pública y su posible influencia en el comportamiento electoral.

Para garantizar la calidad de los datos y obtener conclusiones válidas, es necesario realizar un Análisis Exploratorio de Datos (EDA) antes de proceder con cualquier modelado estadístico o inferencia.

La base de datos contiene las siguientes variables:

Variable Tipo de Variable Categoría/Tipo Descripción
Edad Numérica Continua Años cumplidos
Género Categórica Nominal Identificación de género (Masculino, Femenino, No Binario)
Nivel de Educación Categórica Ordinal Último nivel educativo alcanzado (Primaria, Secundaria, Universitaria, Posgrado)
Ingreso Mensual Numérica Continua Ingresos mensuales en moneda local
Interés en Política Categórica Ordinal Nivel de interés en política (Escala Likert del 1 al 5)
Frecuencia de Voto Categórica Ordinal Frecuencia con la que vota (Nunca, A veces, Siempre)
Ideología Política Categórica Nominal Identificación ideológica (Izquierda, Centro, Derecha)
Confianza en el Gobierno Categórica Ordinal Nivel de confianza en el gobierno (Escala Likert del 1 al 10)
Uso de Redes para Informarse Categórica Ordinal Nivel de uso de redes sociales para informarse (Bajo, Medio, Alto)
Participación en Protestas Categórica Nominal Si ha participado en protestas (Sí, No)

Ahora si, a relizar un análisis Exploratorio de datos EDA

1.3 Instalar y Cargar paquetes

Lo primero que tenemos que hacer es cargar los paquetes que vamos a utilizar para el análisis. En este caso vamos a usar:

library(tidyverse)# Incluye paquetes de importación, visualización entre otros
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr     1.1.4     ✔ readr     2.1.5
## ✔ forcats   1.0.0     ✔ stringr   1.5.1
## ✔ ggplot2   3.5.1     ✔ tibble    3.2.1
## ✔ lubridate 1.9.4     ✔ tidyr     1.3.1
## ✔ purrr     1.0.2     
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag()    masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(dplyr)# Manipulación de Datos
library(ggplot2)# Visualización de datos 
library(readxl)# Importación de datos
library(tibble)# Tablas
library(readr) #Para cargar la base de datos

Recordar que si no ha instalado estos paquetes debe correr primero el comando: install.packages("nombre del paquete"), Recuerde que los paquetes deben instalarse una única vez

Algunos paquetes utilizados para importar y exportar bases de datos en R son:

Algunos paquetes utilizados para importar y exportar bases de datos en R y Python son:

  • utils: permite importar y exportar datos en varios formatos.
  • rgdal: permite importar y exportar datos geoespaciales.
  • readr: permite importar y exportar datos en varios formatos.
  • readxl: Importar datos en formato “Excel”.
  • haven: Importar y exportar datos en “SPSS”, “Stata” y “SAS”.
  • httr: Herramientas para trabajar con URLs y archivos HTTP.
  • rvest: útil para extraer información de las páginas web.
  • xml2: Leer archivos HTML o XML.
  • csv: Importar y exportar datos .csv.
  • pandas: Importar y exportar datos .csv, Excel, SAS, SPSS, html, stata, sql, etc.

1.4 Cargar base de datos:

Tenga en cuenta que debe utilizar la dirección de donde está guardada la base de datos en caso de usar Rstudio descargado en su equipo, o importarlo en la carpeta files en caso de estar trabajando en Rstudio cloud. Aquí puede ir a un video acerca de importación de datos o datasets: (Ver video para Rstudio de escritorio) o también (Ver video para Rstudio Cloud)**

datos <- read_csv("DATA/dataset_opinion_publica.csv") #Ojo esta es la dirección en la que la profe tenía guardados sus datos, es necesario cambiarla.
## Rows: 500 Columns: 10
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (6): genero, nivel_de_educacion, frecuencia_de_voto, ideologia_politica,...
## dbl (4): edad, ingreso_mensual, interes_en_politica, confianza_en_gobierno
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.

Nombres de variables Aquí podemos ver qué variables fueron importadas en nuestro Data Frame:

names(datos)# nombres de variables
##  [1] "edad"                    "genero"                 
##  [3] "nivel_de_educacion"      "ingreso_mensual"        
##  [5] "interes_en_politica"     "frecuencia_de_voto"     
##  [7] "ideologia_politica"      "confianza_en_gobierno"  
##  [9] "uso_de_redes_informarse" "participacion_protestas"

Mostrar o llamar una variable

head(datos$nivel_de_educacion) #Se utiliza el simbilo $ despues del nombre de la base. Se uba la función head para mostrar solo los primero sdatos y no todos.
## [1] "Secundaria"    "Universitaria" "Universitaria" "Posgrado"     
## [5] "Universitaria" "Universitaria"

Dimensiones

Es importante conocer las dimensiones del Dataset cargado para asegurarse que se incluyeron todas las variables y observaciones.

dim(datos) #Dimensiones: num filas x num columnas
## [1] 500  10

Mostrar las primeras filas de la base de datos

head(datos)

Tipos de datos Con esto es posible verificar que los datos están correctamente cargados de acuerdo a la naturaleza de cada variable:

str(datos)
## spc_tbl_ [500 × 10] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
##  $ edad                   : num [1:500] 56 69 46 32 60 25 78 38 56 75 ...
##  $ genero                 : chr [1:500] "Femenino" "No binario" "Masculino" "Masculino" ...
##  $ nivel_de_educacion     : chr [1:500] "Secundaria" "Universitaria" "Universitaria" "Posgrado" ...
##  $ ingreso_mensual        : num [1:500] 2333 1692 6550 3327 5944 ...
##  $ interes_en_politica    : num [1:500] 4 1 3 1 5 4 7 5 10 4 ...
##  $ frecuencia_de_voto     : chr [1:500] "A veces" "Siempre" "Siempre" "Siempre" ...
##  $ ideologia_politica     : chr [1:500] "Centro" "Derecha" "Centro" "Centro" ...
##  $ confianza_en_gobierno  : num [1:500] 1 6 5 9 2 8 5 2 10 6 ...
##  $ uso_de_redes_informarse: chr [1:500] "Alto" "Medio" "Medio" "Alto" ...
##  $ participacion_protestas: chr [1:500] "No" "No" "No" "No" ...
##  - attr(*, "spec")=
##   .. cols(
##   ..   edad = col_double(),
##   ..   genero = col_character(),
##   ..   nivel_de_educacion = col_character(),
##   ..   ingreso_mensual = col_double(),
##   ..   interes_en_politica = col_double(),
##   ..   frecuencia_de_voto = col_character(),
##   ..   ideologia_politica = col_character(),
##   ..   confianza_en_gobierno = col_double(),
##   ..   uso_de_redes_informarse = col_character(),
##   ..   participacion_protestas = col_character()
##   .. )
##  - attr(*, "problems")=<externalptr>

Vemos que las variables Interés en política y Confianza en el gobierno son de naturaleza categórica, sin embargo, R las leyó como numéricas. Se debe corregir de la siguiente manera:

#Convertir variables en factores
datos$interes_en_politica <- as.factor(datos$interes_en_politica) #OJO: con el signo "$" llamo a una variable específica de mi dataset
datos$confianza_en_gobierno <- as.factor(datos$confianza_en_gobierno)

Revisar nuevamente el Dataset:

str(datos)
## spc_tbl_ [500 × 10] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
##  $ edad                   : num [1:500] 56 69 46 32 60 25 78 38 56 75 ...
##  $ genero                 : chr [1:500] "Femenino" "No binario" "Masculino" "Masculino" ...
##  $ nivel_de_educacion     : chr [1:500] "Secundaria" "Universitaria" "Universitaria" "Posgrado" ...
##  $ ingreso_mensual        : num [1:500] 2333 1692 6550 3327 5944 ...
##  $ interes_en_politica    : Factor w/ 10 levels "1","2","3","4",..: 4 1 3 1 5 4 7 5 10 4 ...
##  $ frecuencia_de_voto     : chr [1:500] "A veces" "Siempre" "Siempre" "Siempre" ...
##  $ ideologia_politica     : chr [1:500] "Centro" "Derecha" "Centro" "Centro" ...
##  $ confianza_en_gobierno  : Factor w/ 10 levels "1","2","3","4",..: 1 6 5 9 2 8 5 2 10 6 ...
##  $ uso_de_redes_informarse: chr [1:500] "Alto" "Medio" "Medio" "Alto" ...
##  $ participacion_protestas: chr [1:500] "No" "No" "No" "No" ...
##  - attr(*, "spec")=
##   .. cols(
##   ..   edad = col_double(),
##   ..   genero = col_character(),
##   ..   nivel_de_educacion = col_character(),
##   ..   ingreso_mensual = col_double(),
##   ..   interes_en_politica = col_double(),
##   ..   frecuencia_de_voto = col_character(),
##   ..   ideologia_politica = col_character(),
##   ..   confianza_en_gobierno = col_double(),
##   ..   uso_de_redes_informarse = col_character(),
##   ..   participacion_protestas = col_character()
##   .. )
##  - attr(*, "problems")=<externalptr>

1.5 Revisión de valores faltantes (N/A):

Sumar N/As por cada columna (variable)

# Contar valores faltantes por variable
colSums(is.na(datos))
##                    edad                  genero      nivel_de_educacion 
##                       0                       0                       0 
##         ingreso_mensual     interes_en_politica      frecuencia_de_voto 
##                      10                       0                       0 
##      ideologia_politica   confianza_en_gobierno uso_de_redes_informarse 
##                      10                       0                       0 
## participacion_protestas 
##                      10

Nota importante: Cuando se identifican datos faltantes en un conjunto de datos durante un Análisis Exploratorio de Datos (EDA), es fundamental evaluar su impacto en el análisis y decidir el mejor método para tratarlos. El primer paso consiste en cuantificar la cantidad de valores ausentes y analizar su distribución a lo largo de las variables. Si los valores perdidos son escasos y aleatorios, una opción válida puede ser eliminarlos sin afectar significativamente los resultados. Sin embargo, cuando los valores faltantes son numerosos o siguen un patrón sistemático, es recomendable aplicar métodos de imputación, como el reemplazo por la media o mediana en variables numéricas, o el uso de la moda en variables categóricas. También pueden emplearse técnicas más avanzadas, como la imputación por regresión o el uso de modelos de aprendizaje automático.

En cualquier caso, la decisión sobre el tratamiento de los datos ausentes debe tomarse considerando el contexto del estudio y asegurando que no se introduzcan sesgos que afecten la validez de las conclusiones.

1.6 Revisión de valores atípicos (outliers)

Nota importante: La detección de valores atípicos es un paso crucial en un Análisis Exploratorio de Datos (EDA), ya que estos pueden influir en la interpretación de los resultados y en la robustez de los modelos estadísticos. Un valor atípico es una observación que se aleja significativamente del resto de los datos y puede ser causado por errores de medición, registros incorrectos o, en algunos casos, por la naturaleza de la propia distribución de los datos. Para identificarlos, se pueden utilizar técnicas gráficas como los gráficos de caja y bigotes.

Una vez detectados, es importante analizar su origen: si los valores son producto de errores, pueden ser corregidos o eliminados; si son casos extremos pero válidos, se pueden utilizar transformaciones más complejas para reducir su impacto. La decisión de mantener, corregir o eliminar valores atípicos debe basarse en la naturaleza del problema y el contexto del estudio, asegurando que el análisis refleje con precisión la realidad de los datos.

Un resumen estadístico general de las variables nos puede mostrar el resumen de los cinco números para las variables numéricas: (mínimo, primer cuartil, segundo cuartil (que equivale a la mediana), tercer cuartil y valor máximo). Estos cinco números nos brindan una idea de la distribución de los datos: la media se ve alterada por valores extremos, mientras que la mediana no, cuando la media se aleja mucho de la mediana, puede ser un indicador de datos atípicos o extremos.

En este caso, las variables numéricas son Edad e Ingreso mensual:

# Resumen estadístico general
summary(datos)
##       edad          genero          nivel_de_educacion ingreso_mensual   
##  Min.   :18.00   Length:500         Length:500         Min.   :   125.6  
##  1st Qu.:35.00   Class :character   Class :character   1st Qu.:  2634.0  
##  Median :50.00   Mode  :character   Mode  :character   Median :  5268.8  
##  Mean   :50.34                                         Mean   :  6040.2  
##  3rd Qu.:66.00                                         3rd Qu.:  7264.7  
##  Max.   :80.00                                         Max.   :412545.0  
##                                                        NA's   :10        
##  interes_en_politica frecuencia_de_voto ideologia_politica
##  4      : 56         Length:500         Length:500        
##  5      : 56         Class :character   Class :character  
##  8      : 56         Mode  :character   Mode  :character  
##  10     : 53                                              
##  6      : 49                                              
##  9      : 49                                              
##  (Other):181                                              
##  confianza_en_gobierno uso_de_redes_informarse participacion_protestas
##  6      : 59           Length:500              Length:500             
##  8      : 56           Class :character        Class :character       
##  10     : 54           Mode  :character        Mode  :character       
##  7      : 52                                                          
##  1      : 50                                                          
##  3      : 50                                                          
##  (Other):179

Note que la media y mediana de la edad son muy similares, mientras que en el caso de ingreso mensual, se alejan un poco más. Note también que el valor máximo en esta última variable se encuentra alejado del tercer cuartil. Todo esto lo podemos visualizar en un gráfico de Caja y Bigotes:

Caja y bigotes para la variable edad

boxplot(datos$edad, horizontal=TRUE, col='steelblue', main="Boxplot de edad")

Caja y bigotes para la variable Ingreso mensual

# Desactivar notación científica (cuando las cifras son muy largas)
options(scipen=999)

# Generar el boxplot sin notación científica
boxplot(datos$ingreso_mensual, horizontal=TRUE, col='cadetblue4', main="Boxplot de Ingreso Mensual")

El gráfico se ve de esta manera por los valores extremos. Así se vería sin esos datos atípicos:

# Desactivar notación científica
options(scipen=999)

# Generar boxplot sin valores extremos
boxplot(datos$ingreso_mensual, horizontal=TRUE, col='cadetblue4', 
        main="Boxplot de Ingreso Mensual (Sin Valores Extremos)", 
        outline=FALSE)  # Esto elimina los valores atípicos visualmente

En esta ocasión, reemplazaremos los atípicos por el valor de la mediana a manera de imputación:

# Calcular la mediana del ingreso mensual
mediana <- median(datos$ingreso_mensual, na.rm=TRUE)

# Reemplazar valores atípicos con la mediana
datos$ingreso_mensual <- ifelse(datos$ingreso_mensual %in% boxplot.stats(datos$ingreso_mensual)$out, 
                                mediana, 
                                datos$ingreso_mensual)

# Verificar con un nuevo boxplot
boxplot(datos$ingreso_mensual, horizontal=TRUE, col='cadetblue4', 
        main="Boxplot de Ingreso Mensual (Atípicos Reemplazados con Mediana)")

1.7 Exploración de variables:

1.7.1 Representación en tablas:

Tabla de Frecuencia para Nivel de Educación

# Tabla de Frecuencia para Nivel de Educación
tabla_educacion <- table(datos$nivel_de_educacion)
print(tabla_educacion)
## 
##      Posgrado      Primaria    Secundaria Universitaria 
##            78            51           189           182

Tabla de Frecuencia para Ideología Política

# Tabla de Frecuencia para Ideología Política
tabla_ideologia <- table(datos$ideologia_politica)
print(tabla_ideologia)
## 
##    Centro   Derecha Izquierda 
##       181       156       153

Tabla de Frecuencia para interés en política

# Tabla de Frecuencia para interés en política
tabla_interes_pol <- table(datos$interes_en_politica)
print(tabla_interes_pol)
## 
##  1  2  3  4  5  6  7  8  9 10 
## 46 44 47 56 56 49 44 56 49 53

Tabla de frecuencia agrupada para ingreso mensual

# Determinar automáticamente el número de intervalos con la regla de Sturges
num_intervals <- nclass.Sturges(datos$ingreso_mensual)

# Agrupar ingresos en intervalos automáticos
datos$ingreso_grupo <- cut(datos$ingreso_mensual, breaks = num_intervals, include.lowest = TRUE)

# Crear la tabla de frecuencia
tabla_ingreso <- table(datos$ingreso_grupo)

# Convertir en data frame para mejor presentación
tabla_ingreso_df <- as.data.frame(tabla_ingreso)
colnames(tabla_ingreso_df) <- c("Rango de Ingreso", "Frecuencia")

# Calcular la frecuencia relativa
frecuencia_relativa <- prop.table(tabla_ingreso) * 100  # Convertir a porcentaje
tabla_ingreso_df$frecuencia_relativa <- round(frecuencia_relativa, 2)  # Agregar columna con % y redondear

tabla_ingreso_df #Mostrar la tabla resultante

1.8 Gráficos:

Nota: Encuentra aquí la guía de colores para tus gráficos > **(guía de colores)

Gráfico para la variable genero:

ggplot(datos, aes(x = genero, fill = genero)) +  
  geom_bar() +  
  labs(title = "Distribución de Género", x = "Género", y = "Frecuencia") +  
  theme_minimal()

Gráfico para la variable edad:

ggplot(datos, aes(x = edad)) +  
  geom_histogram(bins = 10, fill = "steelblue", color = "black", alpha = 0.7) +  
  labs(title = "Distribución de Edades", x = "Edad", y = "Frecuencia") +  
  theme_minimal()

Gráfico para ingreso mensual

ggplot(datos, aes(x = ingreso_mensual)) +  
  geom_histogram(bins = 10, fill = "cyan4", color = "black", alpha = 0.7) +  
  labs(title = "Distribución del Ingreso Mensual", x = "Ingreso Mensual", y = "Frecuencia") +  
  theme_minimal()
## Warning: Removed 10 rows containing non-finite outside the scale range
## (`stat_bin()`).

Gráfico para ideología

ggplot(datos, aes(x = ideologia_politica, fill = ideologia_politica)) +  
  geom_bar() +  
  labs(title = "Distribución de la Ideología Política", x = "Ideología Política", y = "Frecuencia") +  
  theme_minimal()

Gráfico circular para voto

tabla_voto <- table(datos$frecuencia_de_voto)
df_voto <- as.data.frame(tabla_voto)
colnames(df_voto) <- c("Frecuencia de Voto", "Frecuencia")

ggplot(df_voto, aes(x = "", y = Frecuencia, fill = `Frecuencia de Voto`)) +  
  geom_bar(stat = "identity", width = 1) +  
  coord_polar("y", start = 0) +  
  labs(title = "Frecuencia de Voto (Gráfico Circular)") +  
  theme_void()

1.9 Análisis Bivariado

diagrama de barras agrupadas genero vs votos

# Crear gráfico de barras agrupadas
ggplot(datos, aes(x = frecuencia_de_voto, fill = genero)) +  
  geom_bar(position = "dodge") +  # "dodge" agrupa las barras
  labs(title = "Frecuencia de Voto por Género", x = "Frecuencia de Voto", y = "Cantidad de Personas") +  
  theme_minimal()

diagrama de cajas y bigotes genero vs ingresos mensuales

# Crear el boxplot de ingreso mensual según género
ggplot(datos, aes(x = genero, y = ingreso_mensual, fill = genero)) +  
  geom_boxplot() +  # Agregar boxplot
  labs(title = "Distribución del Ingreso Mensual por Género", 
       x = "Género", 
       y = "Ingreso Mensual") +  
  theme_minimal()
## Warning: Removed 10 rows containing non-finite outside the scale range
## (`stat_boxplot()`).

Diagrama de dispersión Edad vs ingreso

# Relación entre edad e ingreso
ggplot(datos, aes(x = edad, y = ingreso_mensual)) +
  geom_point(alpha = 0.5, color = "blue") +
  geom_smooth(method = "lm", color = "red") +
  theme_minimal() +
  ggtitle("Relación entre Edad e Ingreso")
## `geom_smooth()` using formula = 'y ~ x'
## Warning: Removed 10 rows containing non-finite outside the scale range
## (`stat_smooth()`).
## Warning: Removed 10 rows containing missing values or values outside the scale range
## (`geom_point()`).

Matriz de correlación entre variables numéricas

#Correlación entre variables numéricas 

# Cargar librería necesaria
library(corrplot)
## corrplot 0.95 loaded
# Seleccionar solo las variables numéricas de interés
datos_correlacion <- datos[, c("edad", "ingreso_mensual")]

# Calcular la matriz de correlación
matriz_cor <- cor(datos_correlacion, use = "complete.obs")

# Mostrar matriz de correlación en consola
print(matriz_cor)
##                       edad ingreso_mensual
## edad            1.00000000      0.04279635
## ingreso_mensual 0.04279635      1.00000000

1.10 Conlusiones

El Análisis Exploratorio de Datos (EDA) realizado sobre la encuesta de opinión pública permitió identificar patrones y relaciones clave entre variables sociodemográficas y políticas. A través del análisis de distribuciones, correlaciones y visualizaciones, se detectaron valores faltantes y valores atípicos. El EDA es un paso esencial y no opcional en cualquier investigación cuantitativa, ya que proporciona una comprensión profunda de los datos y permite tomar decisiones informadas sobre el tratamiento de variables y la aplicación de modelos.

Hallazgos

  • Edad : La distribución de edades es relativamente uniforme, sin concentraciones extremas en grupos específicos.

  • Género: Se observó una distribución equilibrada de género en la muestra. El análisis de caja y bigotes mostró que existen diferencias en los ingresos según el género, con una mediana salarial mayor en ciertos grupos.

  • Nivel de Educación: La mayoría de los encuestados tienen estudios universitarios, seguidos de aquellos con educación secundaria. .

  • Ingreso Mensual: Se identificaron valores atípicos, lo que indica la presencia de individuos con ingresos significativamente mayores que el resto. La distribución de ingresos no es homogénea, con una concentración en los rangos medios y menores diferencias por edad.

  • Frecuencia de Voto️ : La mayoría de los encuestados afirmaron votar siempre o a veces, con pocos casos de abstención total.