# Operaciones básicas en R
2 + 2
5 * 3
sqrt(25) # Raíz cuadradaEpidemiología Avanzada con R: De cero a héroe
Módulo 1: Introducción a R, RStudio y Conceptos Básicos
1.1. ¿Qué es R y por qué usarlo?
R es un lenguaje de programación y un entorno estadístico muy utilizado en la ciencia de datos, estadística y machine learning.
🔹 Ventajas de usar R:
✅ Gratuito y de código abierto
✅ Facilidad para Análisis Estadístico con cientos de librerías especializadas
✅ Comunidad activa con foros, tutoriales y documentación
✅ Orientado a Datos, diseñado específicamente para manejar y analizar datos de forma eficiente
1.2. Entorno de Trabajo: RStudio
RStudio es un IDE (Entorno de Desarrollo Integrado) que facilita el trabajo con R. En RStudio, normalmente verás cuatro paneles principales:
1️⃣ Script/Editor: Es similar a una hoja en donde escribes y guardas tu código, para poder reproducirlo siempre y compartirlo con otros investigadores para que puedan reproducir los mismos pasos que te condujeron a tus conclusiones. Algunas personas les gusta tener varios scripts para diferentes partes del analisis (ej: carga y limpieza de datos, analisis exploratorio, generacion de bases de datos limpias para analisis posteriores, analisis descriptivo, modelamiento). Cuando creas un script generalmente se ubica en el cuadrante superior izquierdo, pero puedes arrastrarlo y ubicarlo en la seccion que sea mas comoda para ti .R.
2️⃣ Consola: Es donde ejecutas el código y ves los resultados de correr ese codigo al momento. Todos los codigos que tienes en tu script realmente se correran en la consola y alli veras los resultados o mensajes de alerta. Sin embaro, tambien puedes ejecutar codigos directamente en la consola sin guardarlos en tu script, esto generalmente en situaciones en las que solo quieres verificar como se veria un analisis o output antes de decidir realmente si quieres incorporarlo en tu script final que todos podran replicar. Usualmente esta se ubica en el cuadrante inferior izquierdo.
3️⃣ Environment/History: Muestra los objetos que has creado mediante tus codigos (data frames, matrices, listas, variables, plots, etc.) y el historial de comandos ejecutados. Generalente se ubica en el cuadrante superior derecho.
4️⃣ Plots/Viewer/Files/Help: Generalmente esta seccion se ubica en el cuadrante inferior derecho y te sirve para ver gráficos, ayudar con la navegación de archivos o mostrar vistas previas de reportes. Tambien en la seccion de ayuda, puedes explorar las librerias que tienes disponibles y las funciones que tienes disponible dentro de esas diferentes librerias. Mas adelante iras profundizando en ello, pero para darte un resumen general una libreria es como un paquete de funciones que fueron programadas por alguien en el pasado para agilizar el proceso de escritura de codigo. Por ejemplo, alguien pudo crear una libreria con un listado de funciones para generar un analisis exploratorio escribiendo solo una linea de codigo en lugar de que tu tengas que escribir cientos de lineas para hacer lo mismo que hace la libreria. Es normal que segun tus necesidades vayas encontrando diferentes librerias que se adaptan a tu estilo de escritura y manejo de datos y las vayas incorporando a tu ambiente de trabajo.
💡 Flujo de trabajo típico en RStudio:
1️⃣ Escribes tu código en un archivo .R (script).
2️⃣ Ejecutas línea por línea o en bloque (`Ctrl + Enter` en Windows o `Cmd + Enter` en Mac).
3️⃣ Observas los resultados en la consola y el "Environment". 1.3. Primeros Pasos en la Consola
La consola de R muestra un símbolo > cuando está lista para recibir un comando.
🔹 Ejemplo: Operaciones Básicas
Prueba ejecutar estas operaciones en la consola:
💡 Ejecuta cada línea y observa los resultados en la consola.
🔥 Ejercicio 1.1: Escribe y ejecuta tu primer script en R
Abre RStudio y crea un script nuevo (File > New File > R Script).
En ese script, escribe lo siguiente:
# Imprime "Hola, R" en la consola
print("Hola, R")
# Realiza una operación aritmética de tu elección
resultado <- 10 * 3
resultadoEjecuta el código y observa el resultado en la consola.
✅ Solución 1.1
Si lo hiciste bien, deberías ver dos salidas:
[1] "Hola, R"
[1] 30
Este simple ejercicio te familiariza con la idea de escribir en el script y ejecutar en la consola.
🎯 ¡Felicidades! Has completado el Módulo 1. En el próximo módulo exploraremos estructuras de datos en R.
Módulo 2: Estructuras de Datos en R
En R, hay distintos tipos de estructuras de datos. Piensa en ellas como diferentes “recipientes” para guardar información. Aquí aprenderás los más importantes.
2.1. Vectores
- Un vector es la estructura más básica.
- Todos los elementos deben ser del mismo tipo (numérico, texto, lógico, etc.).
- Se puede ver como una “fila” o “columna” de valores en un Excel, pero en R no hace falta pensar en filas/columnas hasta que lo uses en un data frame o matriz.
Funciones útiles para crear vectores:
c(...): Combina elementos para formar un vector.rep(x, times): Repite el objetox,timesveces.seq(from, to, by): Crea secuencias numéricas.
Operaciones con vectores:
# Crear un vector numérico
numeros <- c(1, 2, 3, 4, 5)
# Suma de todos sus elementos
suma_numeros <- sum(numeros)
# Promedio
promedio_numeros <- mean(numeros)
suma_numeros # 15
promedio_numeros # 32.2. Matrices
- Una matriz es un objeto bidimensional: tiene filas y columnas, pero todos sus elementos deben ser del mismo tipo.
- Podemos usar
matrix()o combinar vectores concbind()(unión por columnas) orbind()(unión por filas).
Creando matrices:
# Crear una matriz de 3x3
mi_matriz <- matrix(1:9, nrow = 3, ncol = 3)
mi_matriz1:9 genera un vector de 1 a 9 que se llena por columnas, a menos que especifiquemos byrow = TRUE.
Indexación en matrices:
mi_matriz[1, ]: Primera fila completa.mi_matriz[, 2]: Segunda columna completa.mi_matriz[2, 2]: Elemento en la fila 2, columna 2.
2.3. Data Frames
- Un data frame es muy parecido a una hoja de cálculo.
- Cada columna puede tener un tipo de dato diferente (numérico, caracter, factor, etc.).
- Cada fila corresponde normalmente a una observación o caso.
Funciones para data frames:
data.frame(...): Crea un data frame.head(df, n) / tail(df, n): Muestra las primeras o últimas filas.str(df): Muestra la estructura interna.dim(df): Dimensiones (número de filas y columnas).
Ejemplo:
pacientes <- data.frame(
ID = 1:3,
Edad = c(23, 45, 31),
Sexo = c("M", "F", "M")
)
pacientes2.4. Listas
- Una lista puede contener cualquier tipo de objeto: vectores, matrices, data frames, ¡incluso otras listas!
- Son contenedores muy flexibles.
mi_lista <- list(
vector_numeros = c(1, 2, 3),
matriz_ejemplo = matrix(1:4, nrow = 2),
df_pacientes = pacientes
)
mi_lista🔥 Ejercicio 2.1
- Crea un vector con 10 valores numéricos aleatorios usando
rnorm(10). - Convierte ese vector en una matriz de 5 filas y 2 columnas.
- Crea un data frame con dos columnas:
- La primera: valores de la primera columna de la matriz creada.
- La segunda: valores categóricos (por ejemplo, “A”, “B”, “C”).
- Crea una lista que contenga el vector original, la matriz y el data frame.
✅ Solución 2.1
# 1. Vector con 10 valores aleatorios
set.seed(123)
vec_aleatorio <- rnorm(10)
vec_aleatorio
# 2. Convertir a matriz
mat_5x2 <- matrix(vec_aleatorio, nrow = 5, ncol = 2)
mat_5x2
# 3. Data frame
df_ejemplo <- data.frame(
valores = mat_5x2[, 1],
categoria = c("A", "B", "A", "C", "B")
)
df_ejemplo
# 4. Lista con los objetos
lista_final <- list(
vector = vec_aleatorio,
matriz = mat_5x2,
df = df_ejemplo
)
lista_final🎯 ¡Felicidades! Has completado el Módulo 2. En el próximo módulo exploraremos Programación en R: Asignación, Funciones, Bucles y Control de Flujo.
Módulo 3: Programación en R (Asignación, Funciones, Bucles, Control de Flujo)
En este módulo profundizaremos en la lógica de programación para automatizar tareas: cómo asignar valores, crear funciones propias y usar bucles.
3.1. Asignación de Variables
Para “darle un nombre” a un valor en R se usa <- o =.
# Asignación de variables
x <- 10
y = 20
z <- x + y # 30🔹 Nota: La convención en R es usar <-, pero = también funciona.
3.2. Creación de Funciones
Una función es un bloque de código reutilizable.
Estructura de una función en R
nombre_de_funcion <- function(arg1, arg2, ...) {
# Instrucciones
# Valor de retorno
}🔹 Componentes clave: - Argumentos: Valores de entrada a la función (ejemplo: arg1, arg2). - Cuerpo: Código interno de la función. - Return(): Indica el valor de salida de la función. Si no se usa, la salida será el último valor calculado.
Ejemplo: Función para calcular la hipotenusa
hipotenusa <- function(cateto1, cateto2) {
# cateto1: longitud del primer cateto
# cateto2: longitud del segundo cateto
# Retorna: la hipotenusa
h <- sqrt(cateto1^2 + cateto2^2)
return(h)
}
hipotenusa(3, 4) # 5🔹 Valores por defecto: Puedes definir valores opcionales en una función:
# Si no se pasa cateto2, se asume como 1
hipotenusa <- function(cateto1, cateto2 = 1) {
sqrt(cateto1^2 + cateto2^2)
}3.3. Control de Flujo: Condicionales
Los condicionales permiten que el programa tome decisiones según ciertas condiciones.
1️⃣ if - else
x <- 5
if (x > 3) {
print("x es mayor que 3")
} else {
print("x es menor o igual que 3")
}2️⃣ ifelse(): versión vectorizada
numeros <- 1:5
ifelse(numeros %% 2 == 0, "Par", "Impar")
# c("Impar", "Par", "Impar", "Par", "Impar")3.4. Bucles (Loops)
Los bucles permiten repetir una serie de pasos automáticamente.
3.4.1. Bucle for
🔹 Estructura:
for (variable_iter in secuencia) {
# Bloque de código
}
🔹 Ejemplo:
for (i in 1:5) {
print(i^2)
}Aquí, i toma los valores 1, 2, 3, 4, 5 secuencialmente y se ejecuta print(i^2) para cada uno.
3.4.2. Bucle while
🔹 Mientras una condición sea verdadera, se repite el bloque:
j <- 1
while (j <= 5) {
print(j^2)
j <- j + 1
}⚠️ Cuidado: Si no actualizas la variable de control (j <- j + 1), el bucle nunca terminará.
🔥 Ejercicio 3.1
- Crea un vector con valores del 1 al 10.
- Utiliza un bucle
forpara imprimir la raíz cuadrada de cada valor. - Dentro del bucle, usa una sentencia
ifpara imprimir un mensaje especial si el valor es mayor a 8.
✅ Solución 3.1
valores <- 1:10
for (i in valores) {
cat("La raíz cuadrada de", i, "es:", sqrt(i), "\n")
if (i > 8) {
cat("¡Este valor es mayor que 8!\n")
}
}🎯 ¡Felicidades! Has completado el Módulo 3. En el próximo módulo exploraremos operaciones básicas y manipulación de datos en R.
Módulo 4: Operaciones Básicas, Manejo de Paquetes y Exploración Inicial
Antes de hacer análisis complejos, es fundamental explorar los datos, revisar cuántas filas hay, qué tipos de variables existen, y detectar valores faltantes. En este módulo también aprenderemos a instalar y cargar librerías en R.
4.1. Instalación y Carga de Paquetes
En R, muchas funciones avanzadas están organizadas en paquetes o librerías que debemos instalar y cargar antes de usarlas. A continuación, veremos cómo descargar un paquete llamado dplyr y cargarlo en la sesión actual. Este paquete es muy útil para manipulación de datos.
🔹 Instalar un paquete (solo una vez):
# Antes de correr cualquier linea de comandos, es necesario instalar y cargar las librerías necesarias en als que se encuentran almacenados esos comandos. Recuerda quitar el símbolo # antes de ejecutar el código de instalacion. Tambien es muy importante que siempre recuerdes que si el software te pide reiniciar la sesion antes de instalar las librerias, deberias hacerlo al menos una vez. Esto puede evitar futuros conflictos por la creacion de diferentes paths para guardar las librerias.
#install.packages("dplyr") # Para correrlo debes remover el simbolo # que esta antes de la funcion install.packages. En R muchas veces queremos hacer anotaciones en nuestro codigo sin que estas se ejecuten en la consola, una forma de hacer eso es anadiendo el simbolo # antes de la funcion que no queremos que se ejecute.🔹 Cargar un paquete en la sesión actual:
library(dplyr) 💡 Nota: install.packages("nombre_paquete") descarga el paquete desde CRAN (repositorio oficial), mientras que library(nombre_paquete) lo carga en la sesión de R. Si intentas ejecutar un código y este no funciona porque la librería no está instalada, deberás instalarla y cargarla antes de volver a intentar ejecutar el código.
4.2. Paquetes Clave para Exploración de Datos
4.2.1. DataExplorer
🔹 Objetivo: Generar reportes automáticos de Exploración de Datos (EDA).
🔹 Funciones importantes: - create_report(data, output_file = "Reporte.html"): Genera un informe HTML con distribuciones, gráficos, valores faltantes, etc. - plot_intro(data): Muestra el número de filas, columnas y tipos de variables. - plot_missing(data): Visualiza valores faltantes (NA).
🔹 Ejemplo:
library(DataExplorer)
data(iris) # Dataset de ejemplo (flores)
plot_intro(iris) # Información básica
plot_missing(iris) # ¿Hay valores NA?
# create_report(iris) # Esta funcion crea un reporte completo del analisis exploratorio que se guardara como archivo html y puedes ejecutra en tu navegador.4.2.2. skimr
🔹 Objetivo: Generar un resumen detallado (summary) de cada columna en un dataset.
🔹 Función principal: skim(data)
🔹 Ejemplo:
library(skimr)
skim(iris)🔹 Salida esperada: Información sobre cada variable, incluyendo: - Media, mediana, máximo y mínimo. - Número de valores únicos y valores faltantes (NA).
4.2.3. knitr
🔹 Objetivo: Crear informes reproducibles en R Markdown. 🔹 Funciones principales: - kable(data): Muestra data frames en formato de tabla. - include_graphics(path): Permite incluir imágenes en un informe R Markdown.
🔹 Ejemplo:
library(knitr)
kable(head(mtcars), caption = "Tabla con las primeras filas de mtcars")🎯 ¡Felicidades! Has completado el Módulo 4. En el próximo módulo exploraremos manipulación y transformación de datos en R con dplyr, tidyr y gtsummary.
Módulo 5: Paquetes para la manipulación y Transformación de Datos
Aprender a limpiar, transformar y presentar datos de forma eficiente es esencial en el análisis de datos. Estos pasos suelen representar la mayor parte del trabajo real en un proyecto de análisis. En este módulo, exploraremos tres librerías clave para la manipulación y transformación de datos en R: dplyr, tidyr y gtsummary. Estas librerías son parte del tidyverse, una colección de paquetes de R diseñados para la ciencia de datos. Cada librería tiene funciones específicas para facilitar la manipulación, transformación y creación de tablas de resumen. Aquí exploraremos algunas de las funciones principales disponibles en cada librería y proporcionaremos ejemplos prácticos.
5.1. dplyr
🔹 Objetivo: Facilitar la manipulación de data frames de manera legible y eficiente.
🔹 Funciones clave: En la filosofía tidyverse, cada una de estas funciones se llama un “verbo”: 1. filter(): Filtrar filas según condición. 2. select(): Seleccionar columnas por nombre o rango. 3. mutate(): Crear o modificar columnas. 4. arrange(): Reordenar filas. 5. group_by() + summarise(): Agrupar por una o más variables y calcular estadísticas agregadas.
🔹 Ejemplo:
library(dplyr)
# Creamos un data frame de ejemplo
df <- data.frame(
sujeto = 1:6,
edad = c(23, 35, 29, 41, 37, 50),
peso = c(60, 80, 70, 85, 76, 90)
)
# Aplicamos transformaciones con dplyr
df %>%
filter(edad > 30) %>% # Solo los mayores de 30
select(sujeto, peso) %>% # Solo esas dos columnas
mutate(IMC = peso / (1.70^2)) %>% # Crear columna IMC
arrange(desc(IMC)) # Ordenar de mayor a menor IMC💡 Nota: Usamos el operador pipe %>%, que se lee como “y luego”.
5.2. tidyr
🔹 Objetivo: Reestructurar data frames, facilitando la conversión entre formatos ancho y largo.
🔹 Funciones clave: - pivot_longer(): Convierte columnas en filas. - pivot_wider(): Convierte filas en columnas. - separate(): Divide una columna en varias. - unite(): Combina varias columnas en una.
# Cargamos el paquete necesario
library(tidyr)
# library(dplyr) # Se usa para manipular datos, ya la habiamos cargado antes, pero si no, tendriamos que volverla a cargar para que funciones como el pipeline %>% funcionen.
# Creamos un dataset de ejemplo en formato ancho
# Supongamos que tenemos datos de ventas por trimestre
df_wide <- data.frame(
Producto = c("A", "B", "C"),
Q1 = c(100, 200, 150),
Q2 = c(120, 210, 180),
Q3 = c(130, 190, 160)
)
# Convertimos el dataset de formato ancho a formato largo
# Esto nos permite trabajar con datos en un formato más ordenado
df_long <- df_wide %>%
pivot_longer(cols = Q1:Q3, names_to = "Trimestre", values_to = "Ventas")
# Mostramos el dataset en formato largo
print(df_long)
# Ahora, revertimos la transformación de largo a ancho
df_wide2 <- df_long %>%
pivot_wider(names_from = "Trimestre", values_from = "Ventas")
# Mostramos el dataset reconvertido a ancho
print(df_wide2)
# Ejemplo de `separate()`: dividir una columna en varias
# Creamos un dataset con nombres compuestos
df_names <- data.frame(Nombre = c("Juan_Pérez", "Ana_López", "Carlos_García"))
df_separated <- df_names %>% separate(Nombre, into = c("Primer_Nombre", "Apellido"), sep = "_")
print(df_separated)
# Ejemplo de `unite()`: combinar varias columnas en una
df_united <- df_separated %>% unite("Nombre_Completo", Primer_Nombre, Apellido, sep = " ")
print(df_united)5.3. gtsummary
🔹 Objetivo: Crear tablas de resumen estadístico listas para reportes o publicación.
🔹 Funciones clave: - tbl_summary(data, by = variable): Genera una tabla de descripciones estadísticas para cada columna, diferenciando por grupos (by). - add_overall(): Agrega una columna con el total global. - add_p(): Calcula y agrega valores p para comparar subgrupos.
🔹 Ejemplo:
# Cargar las librerías necesarias
library(gtsummary) # Para crear tablas de resumen
library(dplyr) # Para manipulación de datos
# Crear un conjunto de datos de ejemplo (solo si df no está definido)
set.seed(123) # Para reproducibilidad
df <- data.frame(
subject = 1:100,
age = sample(20:80, 100, replace = TRUE),
weight = sample(50:100, 100, replace = TRUE)
)
# Crear una variable categórica basada en el peso
df <- df %>%
mutate(weight_category = ifelse(weight > 75, "Por encima de 75", "75 o menos"))
# Crear la tabla resumen con gtsummary
tbl_summary(df, by = weight_category) %>% # Agrupar por la nueva variable categórica
add_overall() %>% # Agregar la columna de total general
add_p() # Calcular y agregar valores p para la comparación entre grupos💡 Explicación: Aquí dividimos la muestra en peso > 75 y peso <= 75, agregamos la columna Overall, y calculamos un valor p para comparar subgrupos.
🎯 ¡Felicidades! Has completado el Módulo 5. En el próximo módulo exploraremos Análisis Exploratorio de Datos (EDA) en profundidad.
Módulo 6: Visualización y Gestión de Gráficos con ggplot2
La visualización de datos es una herramienta esencial en el análisis estadístico, ya que permite entender patrones, detectar anomalías y comunicar hallazgos de manera efectiva.
En este módulo, aprenderemos a:
✅ Comprender los conceptos fundamentales de ggplot2. ✅ Crear gráficos básicos y avanzados. ✅ Personalizar visualizaciones para mejorar la interpretación. ✅ Explorar diferentes tipos de gráficos según la naturaleza de los datos.
6.1 Introducción a ggplot2
ggplot2 es el paquete de R más utilizado para crear visualizaciones de datos. Está basado en la Gramática de los Gráficos (Grammar of Graphics), lo que permite construir gráficos de manera estructurada y modular.
La filosofía de ggplot2 se basa en la idea de que un gráfico está compuesto por capas, donde cada capa añade información visual específica.
Estructura básica de ggplot2
Un gráfico en ggplot2 sigue una sintaxis con los siguientes elementos:
ggplot(data, aes(x = variable_x, y = variable_y)) +
geom_tipo_de_gráfico() +
otras_funciones_de_personalización()
Componentes clave:
ggplot(data, aes(...))- Define el dataset y las variables a representar.
aes(x = ..., y = ...)indica qué variable se graficará en cada eje.
- Define el dataset y las variables a representar.
geom_*()(Geometría del gráfico)- Especifica el tipo de gráfico a crear, por ejemplo:
geom_point()(dispersión)geom_bar()(barras)geom_boxplot()(boxplot)geom_histogram()(histograma)geom_line()(líneas)
- Especifica el tipo de gráfico a crear, por ejemplo:
- Funciones adicionales para personalizar
labs(): Agrega títulos y etiquetas.theme(): Modifica la apariencia del gráfico.facet_wrap(): Divide el gráfico en paneles por una variable categórica.scale_*(): Personaliza colores, tamaños y ejes.
Instalación y carga del paquete
Si ggplot2 no está instalado, puedes hacerlo con:
# install.packages("ggplot2") # Quita el simbolo # ubicado al comienzo de esta linea si aun no está instalada la libreria en tu computadorPara cargarlo en tu sesión de R:
# install.packages("ggplot2") # Si no está instalado
library(ggplot2)Argumentos clave dentro de aes()
La función aes() (aesthetic mappings) define qué variables se grafican y cómo se asignan a elementos visuales.
| Argumento | Descripción |
|---|---|
x = |
Variable en el eje X |
y = |
Variable en el eje Y |
color = |
Color de los puntos/líneas por categoría |
fill = |
Color de relleno en barras o áreas |
size = |
Tamaño de los puntos/líneas |
alpha = |
Transparencia (1 = sólido, 0 = transparente) |
shape = |
Forma de los puntos en dispersión |
Tipos de geom_*() disponibles
Función geom_*() |
Descripción |
|---|---|
geom_point() |
Gráfico de dispersión |
geom_bar() |
Gráfico de barras |
geom_boxplot() |
Boxplot (distribución) |
geom_histogram() |
Histograma |
geom_line() |
Gráfico de líneas |
geom_smooth() |
Línea de tendencia |
Personalización con labs(), theme(), scale_*()
Una vez creado el gráfico, podemos mejorarlo visualmente:
labs(): Agrega títulos y etiquetas personalizadas.theme_minimal(),theme_classic(): Cambia la apariencia del gráfico.scale_fill_manual(),scale_color_manual(): Modifica colores.facet_wrap(~ variable): Divide gráficos en paneles según una variable categórica.
Estructura basica hasta ahora
✅ ggplot2 permite crear gráficos en capas, combinando datos y elementos visuales. ✅ La función aes() define la asignación de variables a elementos gráficos. ✅ geom_*() define el tipo de gráfico a utilizar. ✅ Se pueden personalizar los gráficos con labs(), theme(), scale_*() y facet_wrap().
Ahora que comprendemos la estructura básica de ggplot2, exploraremos ejemplos prácticos en las siguientes secciones.
Con el objetivo de generar gráficos, utilizaremos el conjunto de datos dat de la base de datos NHANES. Este conjunto de datos contiene información sobre la presión arterial, la edad, las horas de sueño, la actividad física y el estado de tabaquismo en una muestra de la población de EE. UU.
# Instalar y cargar las librerías necesarias. Recuerda quitar el símbolo # antes de ejecutar el código. Si el software te pide reiniciar la sesion antes de instalar las librerias, hazlo al menos una vez. Esto puede evitar futuros conflictos por la creacion de diferentes paths para las librerias.
#install.packages(c("NHANES", "dplyr", "gtsummary", "skimr", "DataExplorer"))
library(NHANES)
library(dplyr)
library(gtsummary)
library(skimr)
library(DataExplorer)
# Selecciona las variables de interes
dat <- NHANES::NHANESraw %>%
dplyr::select(BPSysAve, Age, SleepHrsNight, PhysActive,
SmokeNow, Smoke100, Gender, Race1, Poverty, Diabetes)
head(dat)
## Manejando valores faltantes y convirtiendo variables a factores
# Cuenta de valores faltantes en la variable
sum(is.na(dat$Gender))
# Resumen de valores faltantes
colSums(is.na(dat))
# Visualizacion con DataExplorer
plot_missing(dat)
# Alternativa con skimr
skim(dat)
# Convierte las variables a factores
dat$Gender <- as.factor(dat$Gender)
dat$Race1 <- as.factor(dat$Race1)
# Crea una variable para el habito de fumar
dat <- dat %>%
mutate(SmokingStatus = case_when(
SmokeNow == "Yes" ~ "Current",
Smoke100 == "Yes" ~ "Former",
TRUE ~ "Never"
)) %>%
mutate(SmokingStatus = factor(SmokingStatus))6.2. Gráficos Básicos con ggplot2
A continuación, exploraremos distintos tipos de gráficos con ejemplos prácticos.
6.2.1. Gráfico de Barras
Representa la distribución de variables categóricas.
ggplot(dat, aes(x = Gender)) +
geom_bar(fill = "steelblue") +
labs(title = "Distribución por Género",
x = "Género",
y = "Frecuencia") +
theme_minimal()🔹 Barras apiladas por categoría
ggplot(dat, aes(x = Gender, fill = SmokingStatus)) +
geom_bar(position = "stack") +
labs(title = "Género y Estado de Tabaquismo") +
theme_minimal()🔹 Barras en proporciones
ggplot(dat, aes(x = Gender, fill = SmokingStatus)) +
geom_bar(position = "fill") +
labs(title = "Proporción de Estado de Tabaquismo por Género",
y = "Proporción") +
theme_minimal()6.2.2. Gráfico de Sectores (Pie Chart)
Aunque los gráficos de pastel no son recomendados en publicaciones científicas, pueden ser útiles en informes visuales.
library(dplyr)
df_diab <- dat %>%
count(Diabetes) %>%
mutate(prop = n / sum(n))
ggplot(df_diab, aes(x = "", y = prop, fill = Diabetes)) +
geom_bar(stat = "identity") +
coord_polar("y") +
theme_void() +
labs(title = "Distribución de Diabetes")6.2.3. Boxplot (Gráfico de Caja)
Comparación de distribuciones de una variable cuantitativa según una categórica.
ggplot(dat, aes(x = Gender, y = BPSysAve)) +
geom_boxplot(fill = "tomato", alpha = 0.6) +
labs(title = "Presión Sistólica por Género",
x = "Género", y = "Presión Sistólica") +
theme_minimal()6.2.4. Scatterplot (Diagrama de Dispersión)
Para analizar la relación entre dos variables numéricas.
ggplot(dat, aes(x = Age, y = BPSysAve)) +
geom_point(alpha = 0.5, color = "blue") +
geom_smooth(method = "lm", se = FALSE, color = "red") +
labs(title = "Relación entre Edad y Presión Sistólica",
x = "Edad", y = "Presión Sistólica") +
theme_minimal()6.2.5. Histograma y Curva de Densidad
🔹 Histograma
ggplot(dat, aes(x = BPSysAve)) +
geom_histogram(bins = 30, fill = "lightblue", color = "black") +
labs(title = "Histograma de Presión Sistólica",
x = "Presión Sistólica", y = "Frecuencia") +
theme_minimal()🔹 Curva de densidad
ggplot(dat, aes(x = BPSysAve)) +
geom_density(fill = "lightgreen", alpha = 0.5) +
labs(title = "Densidad de Presión Sistólica") +
theme_minimal()6.3. Personalización Avanzada en ggplot2
ggplot(dat, aes(x = Age, y = BPSysAve)) +
geom_point(color = "darkblue") +
theme_classic() +
theme(
text = element_text(size = 12),
axis.text.x = element_text(color = "blue", size = 11),
axis.text.y = element_text(color = "blue", size = 11),
plot.title = element_text(face = "bold", hjust = 0.5)
) +
labs(title = "Relación entre Edad y Presión Sistólica")6.4. Ejercicio Práctico
Realiza las siguientes tareas con ggplot2:
✅ Crea un gráfico de barras para visualizar la distribución de Race1.
✅ Genera un boxplot comparando SleepHrsNight según PhysActive.
✅ Construye un scatterplot entre Age y SleepHrsNight con una línea de tendencia.
✅ Aplica personalización en los gráficos.
🔹 Resumen del Módulo
✅ Entendimos la gramática de ggplot2.
✅ Aprendimos a crear gráficos de barras, boxplots, histogramas y dispersión.
✅ Exploramos cómo personalizar gráficos para mejorar la comunicación.
✅ Realizamos ejercicios prácticos para reforzar el aprendizaje.
🎯 ¡Felicidades! Has completado el Módulo 6. En el próximo módulo exploraremos Análisis Exploratorio de Datos (EDA).
Módulo 7: Análisis Exploratorio de Datos (EDA)
El Análisis Exploratorio de Datos (EDA) es un paso fundamental en cualquier análisis estadístico o de machine learning. Su propósito es entender la estructura de los datos, identificar patrones, detectar valores atípicos (outliers) y verificar la calidad de los datos antes de aplicar modelos.
Este módulo guiará al estudiante a través de una estrategia estructurada de EDA y proporcionará ejemplos prácticos con herramientas en R.
7.1. Estrategia de Análisis Exploratorio de Datos (EDA)
Un buen análisis exploratorio sigue una serie de pasos lógicos para evaluar la calidad de los datos y sus relaciones:
1️⃣ Identificación de valores faltantes (NAs) / Missing Values Identification
Los valores faltantes pueden influir en los resultados de un análisis. Es importante detectarlos y decidir cómo manejarlos (eliminación, imputación, etc.).
# Cargando un dataset incluido / Loading a built-in dataset
df_iris <- iris # Copiamos el dataset 'iris' a un nuevo objeto df_iris / Copying 'iris' dataset to a new object df_iris
# Si tienes un dataset en Excel / If you have an Excel dataset
# df_tus_datos <- readxl::read_excel("ruta_a_tu_archivo.xlsx")
# Si tienes un dataset en CSV / If you have a CSV dataset
# df_tus_datos <- readr::read_csv("ruta_a_tu_archivo.csv")
# Contar valores faltantes en cada columna / Count missing values in each column
colSums(is.na(df_iris))
# Visualizar valores faltantes gráficamente / Visualize missing values graphically
plot_missing(df_iris)Nota: Aunque usamos el dataset iris incluido en R por conveniencia, puedes cargar tus propios datos si los tienes almacenados en otro lugar. Por ejemplo, si tu archivo está guardado en formato Excel, puedes usar funciones como readxl::read_excel("ruta_al_archivo.xlsx"). De manera similar, si tienes un archivo CSV, podrías usar readr::read_csv("ruta_al_archivo.csv"). En ambos casos, es importante indicar la ruta correcta del archivo para que R pueda localizar y cargar los datos.
2️⃣ Análisis univariado: distribución de variables / Univariate Analysis: Variable Distribution
Para entender la distribución de una variable, usamos: - Variables numéricas: Histogramas y boxplots. - Variables categóricas: Tablas de frecuencias y gráficos de barras.
También podemos crear nuevas variables basadas en las existentes para análisis o para generar tablas que comparen grupos en nuestros datos.
# Histogramas para variables numéricas / Histograms for numerical variables
plot_histogram(df_iris)
# Boxplots por categoría / Boxplots by category
plot_boxplot(df_iris, by = "Species")
# Crear una variable dummy para simular un desenlace binario
# Para este ejemplo la variable 'Outcome' tomará el valor 'High' si Sepal.Length > 5.8 y 'Low' en caso contrario.
# Esto nos permite analizar la distribución de la variable categórica en relación con la especie.
df_iris$Outcome <- ifelse(df_iris$Sepal.Length > 5.8, "High", "Low")
# Convertir la variable en factor para análisis categórico
# Esto facilita su uso en tablas de frecuencia y gráficos.
df_iris$Outcome <- as.factor(df_iris$Outcome)
# Gráfico de barras con porcentajes por desenlace / Bar chart with percentages by outcome
library(ggplot2)
ggplot(df_iris, aes(x = Species, fill = Outcome)) +
geom_bar(position = "fill") +
scale_y_continuous(labels = scales::percent) +
labs(title = "Distribución de Outcome por Species / Outcome Distribution by Species",
x = "Especie / Species",
y = "Porcentaje / Percentage",
fill = "Outcome") +
theme_minimal()
# Tabla de frecuencias
table(df_iris$Species)
# Tabla de proporciones
prop.table(table(df_iris$Species), margin = 1)
# Frecuencia de Outcome por Species (esto es más un análisis bivariado, pero es útil para entender la distribución de la variable de resultado por especie)
table(df_iris$Species, df_iris$Outcome)
# Tabla de proporciones por desenlace (esto es más un análisis bivariado, pero es útil para entender la distribución de la variable de resultado por especie)
prop.table(table(df_iris$Species, df_iris$Outcome), margin = 1)3️⃣ Análisis bivariado: relaciones entre variables
En el paso 2 mostramos cómo podríamos generar un análisis bivariado para entender la distribución de la variable de resultado por especie. También podríamos explorar las relaciones entre diferentes variables usando:
- Variables numéricas: Matrices de correlación, scatterplots.
- Variables categóricas: Tablas de contingencia, pruebas de independencia.
- Numéricas vs. Categóricas: Boxplots por categoría, pruebas estadísticas.
# Análisis Bivariado: Relaciones entre Variables
## 1. Matriz de Correlación para Variables Numéricas
# Eliminamos la columna 'Species' para evitar confusión (ya que es categórica)
df_numericas <- df_iris[, sapply(df_iris, is.numeric)] # Conservamos solo las columnas numéricas
# Visualización de la matriz de correlación sin variables categóricas
plot_correlation(df_numericas)
# Alternativamente, podemos calcular la matriz de correlación numéricamente con cor()
cor(df_numericas, use = "complete.obs")## 2. Gráfico de Dispersión para Visualizar la Relación entre Sepal Length y Sepal Width
library(ggplot2)
ggplot(df_iris, aes(x = Sepal.Length, y = Sepal.Width, color = Species)) +
geom_point() +
geom_smooth(method = "lm", se = FALSE) + # Agrega una línea de regresión lineal
labs(title = "Gráfico de Dispersión entre Sepal Length y Sepal Width",
x = "Longitud del Sépalo",
y = "Ancho del Sépalo",
color = "Especie") +
theme_minimal()## 3. Boxplots: Comparación de Variables Numéricas vs. Categóricas
# Comparación de la distribución de Sepal.Length entre especies
ggplot(df_iris, aes(x = Species, y = Sepal.Length, fill = Species)) +
geom_boxplot() +
labs(title = "Boxplot de Sepal Length por Especie",
x = "Especie",
y = "Longitud del Sépalo") +
theme_minimal()
# Comparación de la distribución de Sepal.Width según el Outcome
ggplot(df_iris, aes(x = Outcome, y = Sepal.Width, fill = Outcome)) +
geom_boxplot() +
labs(title = "Boxplot de Sepal Width por Outcome",
x = "Outcome",
y = "Ancho del Sépalo") +
theme_minimal()## 4. Tablas de Contingencia para Variables Categóricas
# Análisis de la relación entre Species y Outcome
table(df_iris$Species, df_iris$Outcome)
# Convertir la tabla en proporciones (porcentaje por fila)
prop.table(table(df_iris$Species, df_iris$Outcome), margin = 1)
# Visualización de la relación categórica con un gráfico de barras apiladas
ggplot(df_iris, aes(x = Species, fill = Outcome)) +
geom_bar(position = "stack") +
labs(title = "Gráfico de Barras Apiladas de Outcome por Especie",
x = "Especie",
y = "Frecuencia",
fill = "Outcome") +
theme_minimal()
# Prueba de Chi-cuadrado para evaluar la independencia entre Species y Outcome
chisq.test(table(df_iris$Species, df_iris$Outcome))4️⃣ Detección de outliers y datos inconsistentes
Los valores extremos se identifican en boxplots y con el criterio de Tukey. También se revisan combinaciones ilógicas de datos (ej., valores negativos en variables que no lo permiten).
Los valores extrepos suelen ser detectados usando: - Boxplots, que proporcionan un resumen visual de las distribuciones. - El Criterio de Tukey, que define outliers como valores fuera de 1.5 veces el rango intercuartílico (IQR). - Gráficos de densidad, que pueden revelar valores extremos y distribuciones multimodales.
Otros tipos de gráficos que podemos usar son los violin plots, que son similares a los box plots, pero también muestran la densidad de probabilidad de los datos en diferentes valores. En el dataset de ejemplo no tenemos valores extremos asi que nos reportara cero outliers.
# Cargamos una libreria necesaria para la visualizacion de graficos
library(ggplot2)
# Los violin plots son generados con la funcion geom_violin()
ggplot(df_iris, aes(x = Species, y = Sepal.Length, fill = Species)) +
geom_violin(alpha = 0.5) + # Adds violin plot for better distribution visualization
geom_jitter(width = 0.1, aes(color = Species), size = 1.5, alpha = 0.7) + # Adds individual data points
geom_boxplot(width = 0.2, outlier.shape = NA, alpha = 0.6) + # Adds boxplot without outliers
labs(title = "Distribution of Sepal Length by Species",
x = "Species",
y = "Sepal Length") +
theme_minimal()# Calculate the interquartile range (IQR)
Q1 <- quantile(df_iris$Sepal.Length, 0.25)
Q3 <- quantile(df_iris$Sepal.Length, 0.75)
IQR <- Q3 - Q1
# Define lower and upper bounds for outliers
lower_bound <- Q1 - 1.5 * IQR
upper_bound <- Q3 + 1.5 * IQR
# Identify outliers
outliers <- df_iris %>%
filter(Sepal.Length < lower_bound | Sepal.Length > upper_bound)
# Display detected outliers
print(outliers)
# Highlight outliers in a scatter plot
ggplot(df_iris, aes(x = Species, y = Sepal.Length, color = Sepal.Length < lower_bound | Sepal.Length > upper_bound)) +
geom_jitter(width = 0.2, size = 2) +
scale_color_manual(values = c("black", "red"), labels = c("Normal", "Outlier")) +
labs(title = "Outlier Detection in Sepal Length",
x = "Species",
y = "Sepal Length",
color = "Status") +
theme_minimal()🔹 Resumen del módulo
✅ EDA es clave antes de cualquier análisis o modelado.
✅ Evaluamos la calidad de los datos (valores faltantes, outliers, inconsistencias).
✅ Analizamos distribuciones y relaciones entre variables (correlaciones, tablas de frecuencia).
✅ Usamos herramientas como DataExplorer, skimr, dplyr y gtsummary para hacer un análisis rápido y efectivo.
✅ Ejercicio práctico: Aplicar EDA a otro dataset para reforzar lo aprendido.
🎯 ¡Felicidades! Has completado el Módulo 7. En el próximo módulo exploraremos Análisis Estadístico Descriptivo y Analítico en R.
Módulo 8: Análisis Estadístico Descriptivo y Analítico
El análisis estadístico descriptivo y analítico permite resumir, explorar y comparar datos antes de aplicar modelos más complejos. En este módulo aprenderemos a:
✅ Importar y manejar datos. ✅ Procesar datos faltantes. ✅ Crear y recodificar variables. ✅ Realizar análisis descriptivo univariado. ✅ Comparar subgrupos mediante análisis bivariado. ✅ Construir tablas descriptivas personalizadas con gtsummary.
Para este analisis, usaremos el mismo dataset dat de la base NHANES que habiamos estado utilizando en los módulos anteriores cuando revisamos ggplot2.
# Instalar y cargar las librerías necesarias. Recuerda quitar el símbolo # antes de ejecutar el código. Si el software te pide reiniciar la sesion antes de instalar las librerias, hazlo al menos una vez. Esto puede evitar futuros conflictos por la creacion de diferentes paths para las librerias.
#install.packages(c("NHANES", "dplyr", "gtsummary", "skimr", "DataExplorer"))
library(NHANES)
library(dplyr)
library(gtsummary)
library(skimr)
library(DataExplorer)
# Selecciona las variables de interes
dat <- NHANES::NHANESraw %>%
dplyr::select(BPSysAve, Age, SleepHrsNight, PhysActive,
SmokeNow, Smoke100, Gender, Race1, Poverty, Diabetes)
head(dat)7.1. Recordatorio: Importación de Datos
En este curso trabajaremos con dat de NHANES. Sin embargo, en condiciones reales es muy posible que utilicemos nuestros propios datos. Para cargar datos de un excel podemos utilizar:
# Instalacion y carga de librerias
# install.packages("readxl")
# library(readxl)
# Importar archivo de Excel
# df_excel <- read_excel("data/ejemplo.xlsx") # Tienes que reemplazar "data/ejemplo.xlsx" con la ruta correcta de tu archivo7.2. Manejo de Datos Faltantes
Los valores faltantes pueden afectar el análisis. Primero, los identificamos:
# Contar valores faltantes en una variable específica
sum(is.na(dat$Gender))
# Resumen de valores faltantes en todo el dataset
colSums(is.na(dat))
# Visualización con DataExplorer
plot_missing(dat)
# Alternativa con skimr
skim(dat)Si hay datos faltantes, podemos eliminarlos (na.omit(dat)) o imputarlos con la mediana:
dat <- dat %>%
mutate(SleepHrsNight = ifelse(is.na(SleepHrsNight), median(SleepHrsNight, na.rm = TRUE), SleepHrsNight))7.3. Creación y Recodificación de Variables
Conversión de variables categóricas
dat$Gender <- as.factor(dat$Gender)
dat$Race1 <- as.factor(dat$Race1)Creación de una variable de hábito de fumar
dat <- dat %>%
mutate(SmokingStatus = case_when(
SmokeNow == "Yes" ~ "Current",
Smoke100 == "Yes" ~ "Former",
TRUE ~ "Never"
)) %>%
mutate(SmokingStatus = factor(SmokingStatus))7.4. Análisis Descriptivo Univariado
Frecuencias y estadísticas básicas
# Frecuencia de Género
table(dat$Gender)
# Frecuencia de Estado de Fumador
table(dat$SmokingStatus)
# Resumen estadístico de la edad
summary(dat$Age)
# Media y desviación estándar de la presión arterial
mean(dat$BPSysAve, na.rm = TRUE)
sd(dat$BPSysAve, na.rm = TRUE)7.5. Análisis Bivariado
Comparación de una variable numérica entre grupos (t-test)
t.test(Age ~ Gender, data = dat)ANOVA para más de dos grupos
anova_model <- aov(Age ~ Race1, data = dat)
summary(anova_model)Tablas de contingencia y chi-cuadrado
tab <- table(dat$SmokingStatus, dat$Gender)
chisq.test(tab)
xtabs(~ SmokingStatus + Gender, data = dat)7.6. Análisis Descriptivo con gtsummary
Resumen univariado
# Ver las primeras filas de los datos
head(dat)
# Crear tabla resumen con gtsummary
tbl1 <- dat %>%
dplyr::select(BPSysAve, Age, Gender, Diabetes, SmokingStatus) %>%
tbl_summary()
# Deberias poder ver la tabla generada en tu computadora corriendo este comando
# tbl1Comparación por grupo
tbl <- dat %>%
select(BPSysAve, Age, Gender, Diabetes, SmokingStatus) %>%
tbl_summary(
by = Gender,
missing = "ifany",
statistic = list(
all_continuous() ~ "{mean} ({sd})",
all_categorical() ~ "{n} / {N} ({p}%)"
),
label = list(
BPSysAve ~ "Blood Pressure Sys. Ave",
SmokingStatus ~ "Smoking Status"
)
) %>%
add_overall() %>%
add_p() %>%
modify_header(label ~ "**Variable**")
tbl🔥 Ejercicio 7.1: Aplicación en otro dataset
data("airquality")
df_airquality <- airquality
# Paso 1: Ver valores faltantes
plot_missing(df_airquality)
# Paso 2: Convertir temperatura en categoría
df_airquality <- df_airquality %>%
mutate(TempCat = ifelse(Temp > median(Temp, na.rm = TRUE), "Alta", "Baja"))
# Paso 3: Comparación de Ozone por TempCat
t.test(Ozone ~ TempCat, data = df_airquality, na.rm = TRUE)
# Paso 4: Tabla descriptiva
tbl_summary(df_airquality, by = "TempCat")🔹 Resumen del módulo
✅ Exploramos datos faltantes y cómo manejarlos.
✅ Creamos y recodificamos variables para mejorar la interpretación.
✅ Realizamos análisis descriptivo univariado y bivariado.
✅ Generamos tablas profesionales con gtsummary.
✅ Ejercicio práctico para reforzar conocimientos.
🎯 ¡Felicidades! Has completado el Módulo 7. En el próximo módulo exploraremos Visualización y Gestión de Gráficos con ggplot2.
Módulo 9: Fundamentos de Modelado Estadístico
Antes de avanzar a técnicas más avanzadas de machine learning, es fundamental entender los principios del modelamiento estadístico. En este módulo, exploraremos diferentes tipos de regresión, sus aplicaciones, suposiciones y cómo implementarlas en R.
9.1. Regresión Lineal: Modelando Relaciones Continuas
🔹 Concepto y Aplicación La regresión lineal es uno de los modelos más simples y ampliamente utilizados en estadística y machine learning. Se emplea cuando la variable dependiente (respuesta) es continua y se asume que tiene una relación lineal con una o más variables predictoras.
La ecuación del modelo de regresión lineal es: \[ Y = \beta_0 + \beta_1 X_1 + \beta_2 X_2 + \dots + \beta_p X_p + \varepsilon \]
Donde: - ( _0 ) es la intersección (intercepto), el valor de ( Y ) cuando todas las variables ( X_i ) son 0. - ( _i ) representa el cambio en ( Y ) por unidad de cambio en ( X_i ), asumiendo que las demás variables permanecen constantes. - ( ) es el término de error aleatorio, que se supone normalmente distribuido con media 0.
🔹 Suposiciones Clave 1. Linealidad: La relación entre la variable respuesta y los predictores es lineal. 2. Independencia: Las observaciones son independientes entre sí. 3. Homoscedasticidad: La varianza de los residuos es constante. 4. Normalidad de los Errores: Los residuos deben seguir una distribución normal para inferencias válidas.
🔹 Implementación en R
# Cargar datos
data <- read.csv("presion_arterial.csv")
# Ajustar modelo
mod_lin <- lm(PresionSistolica ~ Edad + IMC + Sexo, data = data)
# Resumen del modelo
summary(mod_lin)9.2. Evaluación del Modelo: MSE (Mean Squared Error)
El Error Cuadrático Medio (MSE) mide el promedio de los cuadrados de los errores: \[ MSE = \frac{1}{n} \sum_{i=1}^{n} (y_i - \hat{y}_i)^2 \]
- Un MSE más bajo indica un mejor ajuste.
- Un MSE muy bajo puede indicar overfitting.
🔹 Cálculo en R
# Calcular MSE
mse <- mean((data$PresionSistolica - predict(mod_lin))^2)
print(mse)9.3. Regresión Logística: Modelando Variables Categóricas Binarias
🔹 Concepto y Aplicación Cuando la variable respuesta es dicotómica (ejemplo: presencia o ausencia de enfermedad), la regresión logística modela la probabilidad de ocurrencia de un evento mediante la función logística: \[ P(Y=1) = \frac{e^{\beta_0 + \beta_1 X_1 + \dots + \beta_p X_p}}{1 + e^{\beta_0 + \beta_1 X_1 + \dots + \beta_p X_p}} \]
🔹 Ejemplo en R: Predicción de Diabetes
data$Diabetes <- factor(data$Diabetes, levels = c("No", "Yes"))
mod_logit <- glm(Diabetes ~ Edad + IMC + Sexo, data = data, family = binomial)
summary(mod_logit)
# Presentación con gtsummary
library(gtsummary)
tbl_regression(mod_logit, exponentiate = TRUE)9.4. Regresión Multinomial: Variables con Más de Dos Categorías
Si la variable respuesta tiene más de dos categorías, usamos regresión multinomial.
library(nnet)
data$SmokingStatus <- relevel(data$SmokingStatus, ref = "Never")
mod_multinom <- multinom(SmokingStatus ~ Edad + IMC, data = data)
summary(mod_multinom)9.5. Regresión de Poisson: Modelando Conteos
Para variables de conteo (ejemplo: número de visitas al hospital), se usa regresión de Poisson:
mod_pois <- glm(HospitalVisits ~ Edad + IMC, data = data, family = poisson(link = "log"))
summary(mod_pois)Para razones de prevalencia (RP) con estimaciones robustas, se usa:
library(sandwich)
library(lmtest)
mod_pois_robust <- glm(Diabetes ~ Edad + IMC, data = data, family = poisson(link = "log"))
coeftest(mod_pois_robust, vcov = vcovHC(mod_pois_robust, type = "HC0"))9.6. Regresión de Cox: Análisis de Supervivencia
Para analizar el tiempo hasta un evento (ejemplo: tiempo hasta hospitalización), se usa el modelo de Cox:
library(survival)
# Simulación de datos de supervivencia
data$Tiempo <- round(runif(nrow(data), 1, 1000))
data$Evento <- rbinom(nrow(data), 1, 0.3)
mod_cox <- coxph(Surv(Tiempo, Evento) ~ Edad + IMC, data = data)
summary(mod_cox)9.7. Validación Cruzada: Evaluando la Generalización
🔹 Concepto y Aplicación La validación cruzada permite evaluar la capacidad predictiva de un modelo sin depender de un solo conjunto de datos.
🔹 Implementación en R
library(caret)
ctrl <- trainControl(method = "cv", number = 10)
modelo_cv <- train(PresionSistolica ~ Edad + IMC + Sexo, data = data, method = "lm", trControl = ctrl)
print(modelo_cv)🎯 ¡Felicidades! Has completado el Módulo 9. En el próximo módulo exploraremos Introducción a Librerías de Machine Learning y Tuning de Hiperparámetros.
Módulo 10: Fundamentos de Selección de Modelos y Algoritmos de Aprendizaje Automático
Antes de optimizar hiperparámetros (fine-tuning), es fundamental entender los modelos de aprendizaje automático y sus fundamentos. Este módulo cubre la selección de modelos, regresiones penalizadas, árboles de decisión y modelos de ensamblaje.
10.1 Introducción
Comprender los diferentes enfoques de selección de modelos es clave para construir modelos eficientes y reducir el sobreajuste.
10.2 Selección de Modelos y Variables
10.2.1 Enfoques para la Selección de Variables
- Selección del Mejor Subconjunto: Prueba todas las combinaciones posibles de variables y selecciona la mejor.
- Selección Hacia Adelante (Forward Selection): Comienza con una variable y agrega progresivamente la que mejora el modelo.
- Selección Hacia Atrás (Backward Selection): Comienza con todas las variables y elimina las menos relevantes.
Ejemplo en R
library(leaps)
bestmodels <- regsubsets(BMI ~ ., data = df, nvmax = 8)
summary(bestmodels)10.3 Regresiones Penalizadas: Ridge y Lasso
10.3.1 Concepto de Regularización
La regularización reduce el sobreajuste al agregar un término de penalización a la función de pérdida.
- Lasso (L1): Fomenta la selección de variables.
- Ridge (L2): Reduce la varianza sin eliminar variables.
10.3.2 Implementación en R
library(glmnet)
x <- model.matrix(BMI ~ ., df)[, -1]
y <- df$BMI
lasso.mod <- glmnet(x, y, alpha = 1)
plot(lasso.mod)10.4 Árboles de Decisión y CART
Los árboles de decisión dividen iterativamente los datos según la variable que maximiza la separación.
10.4.1 Hiperparámetros Clave
- Max Depth: Profundidad del árbol.
- Min Samples Split: Número mínimo de observaciones para dividir un nodo.
- Criterion: Métrica de división (Gini o entropía).
10.4.2 Implementación en R
library(rpart)
modelo_cart <- rpart(BMI ~ ., data = df, method = "anova")
plot(modelo_cart); text(modelo_cart)10.5 Modelos de Ensamblaje: Random Forest y Boosting
10.5.1 Random Forest
Combina múltiples árboles para mejorar la estabilidad.
library(randomForest)
modelo_rf <- randomForest(BMI ~ ., data = df, ntree = 500)
importance(modelo_rf)10.5.2 Boosting (XGBoost)
library(xgboost)
dtrain <- xgb.DMatrix(data = x, label = y)
modelo_xgb <- xgboost(data = dtrain, nrounds = 100, max_depth = 3, eta = 0.1)10.6 Fundamentos de Optimización de Modelos
10.6.1 Validación Cruzada
Evalúa el rendimiento del modelo en diferentes particiones del conjunto de datos.
library(caret)
control <- trainControl(method = "cv", number = 5)
modelo_cv <- train(BMI ~ ., data = df, method = "rf", trControl = control)10.6.2 Métricas de Evaluación
- Regresión: Error Cuadrático Medio (MSE), R².
- Clasificación: Precisión, F1-score, ROC-AUC.
pred <- predict(modelo_rf, df)
mean((df$BMI - pred)^2) # MSE10.7 Conclusión
Este módulo proporciona las bases para comprender los modelos de aprendizaje automático antes de ajustar hiperparámetros. En el siguiente módulo, exploraremos estrategias avanzadas de fine-tuning para mejorar el rendimiento del modelo.
Módulo 11: Fine-Tuning y Optimización de Modelos de Aprendizaje Automático
11.1 Introducción
El ajuste fino (fine-tuning) es el proceso de optimizar hiperparámetros para mejorar el rendimiento del modelo. En este módulo, exploraremos métodos para seleccionar valores óptimos y cómo las librerías en R implementan esta optimización.
11.2 Importancia de la Selección de Hiperparámetros
Los hiperparámetros afectan el rendimiento del modelo y deben ajustarse correctamente. Métodos comunes incluyen:
- Búsqueda en Cuadrícula (Grid Search): Evalúa todas las combinaciones posibles dentro de un rango definido.
- Búsqueda Aleatoria (Random Search): Selecciona combinaciones aleatorias y evalúa el rendimiento.
- Optimización Bayesiana: Modela la función de pérdida y ajusta los hiperparámetros iterativamente.
11.3 Métodos para Ajuste de Modelos
11.3.1 Validación Cruzada
La validación cruzada evalúa el rendimiento en diferentes particiones del conjunto de datos.
library(caret)
control <- trainControl(method = "cv", number = 5)
modelo_cv <- train(BMI ~ ., data = df, method = "rf", trControl = control)Aquí, trainControl define el esquema de validación cruzada y train ajusta el modelo con los parámetros definidos.
11.3.2 Selección del Mejor Modelo con Grid Search
param_grid <- expand.grid(mtry = c(2, 4, 6, 8),
min.node.size = c(1, 3, 5),
sample.fraction = c(0.5, 0.7, 0.9))
modelo_tuned <- train(BMI ~ ., data = df, method = "rf",
trControl = control, tuneGrid = param_grid)Aquí, expand.grid genera combinaciones de hiperparámetros, y tuneGrid define la exploración en train.
11.3.3 Selección con Búsqueda Aleatoria
modelo_random <- train(BMI ~ ., data = df, method = "rf",
trControl = control, tuneLength = 10)Aquí, tuneLength = 10 indica que se probarán 10 combinaciones aleatorias de hiperparámetros.
11.3.4 Optimización Bayesiana con mlr3mbo
library(mlr3)
library(mlr3tuning)
learner <- lrn("classif.ranger", predict_type = "prob")
search_space <- ps(mtry = p_int(2, 8),
min.node.size = p_int(1, 10))
instance <- TuningInstanceSingleCrit$new(task = task,
learner = learner,
resampling = rsmp("cv", folds = 5),
measure = msr("classif.auc"),
search_space = search_space,
terminator = trm("evals", n_evals = 20))
tuner <- tnr("mbo")
tuner$optimize(instance)Aquí, mlr3tuning utiliza la optimización bayesiana para encontrar la mejor combinación de hiperparámetros.
11.4 Selección de Hiperparámetros en Diferentes Modelos
11.4.1 Regresiones Penalizadas (Lasso y Ridge)
library(glmnet)
x <- model.matrix(BMI ~ ., df)[, -1]
y <- df$BMI
cv_model <- cv.glmnet(x, y, alpha = 1)
best_lambda <- cv_model$lambda.minAquí, cv.glmnet utiliza validación cruzada para seleccionar el mejor valor de lambda.
11.4.2 Árboles de Decisión y Random Forest
library(randomForest)
modelo_rf <- randomForest(BMI ~ ., data = df, ntree = 500, mtry = 4)
modelo_rf$importanceAquí, mtry define el número de predictores en cada división y se optimiza con validación cruzada.
11.4.3 XGBoost con Optimización de Parámetros
library(xgboost)
dtrain <- xgb.DMatrix(data = as.matrix(df[, -1]), label = df$BMI)
best_model <- xgb.cv(params = list(eta = 0.1, max_depth = 3),
data = dtrain, nrounds = 50, nfold = 5,
objective = "reg:squarederror")Aquí, xgb.cv usa validación cruzada para ajustar eta y max_depth.
11.5 Evaluación del Modelo
Las métricas dependen del tipo de problema:
- Regresión: MSE, R².
- Clasificación: Precisión, F1-score, ROC-AUC.
pred <- predict(modelo_rf, df)
mse <- mean((df$BMI - pred)^2) # Cálculo de MSE11.6 Conclusión del modulo
Este módulo profundiza en la selección y ajuste de hiperparámetros utilizando diversas estrategias. Dependiendo del modelo y los datos, diferentes técnicas pueden ser más efectivas para optimizar el rendimiento del modelo.
Módulo 12: Ensamblado de Modelos - Stacking y Super Learner
El stacking es una técnica de ensamble que combina predicciones de múltiples modelos base (como regresión LASSO, Random Forest, XGBoost) y aprende una combinación óptima de sus predicciones en lugar de elegir un solo “mejor modelo”.
Los ensambles suelen superar a los modelos individuales porque aprovechan sus fortalezas y reducen sus debilidades. En este módulo, exploraremos Super Learner, una implementación en R de esta técnica, usando la base de datos NHANES.
12.1. ¿Qué es Super Learner?
Super Learner es un método de aprendizaje estadístico basado en validación cruzada interna, que selecciona y combina varios modelos predictivos (learners) para mejorar el desempeño del modelo final.
🔹 Diferencias entre Discrete Super Learner y Super Learner
Discrete Super Learner: - Compara el desempeño de varios modelos y selecciona uno solo, el que tenga mejor rendimiento en validación cruzada. - Es un enfoque de selección de modelo, no de combinación. - Puede ser útil cuando se busca interpretabilidad, pero no siempre es la mejor opción en términos de rendimiento.
Super Learner: - No se queda con un solo modelo, sino que combina múltiples modelos usando un meta-learner (usualmente una regresión ponderada). - Se basa en la validación cruzada para asignar pesos óptimos a cada modelo, logrando generalmente un mejor desempeño que cualquier modelo individual. - Es una técnica de ensamble adaptativo, que ajusta la combinación en función de los datos.
👉 Conclusión: En general, Super Learner es más poderoso que el Discrete Super Learner, ya que aprovecha información de múltiples modelos en lugar de depender de uno solo.
12.2. Componentes de un Super Learner
El paquete SuperLearner en R facilita la implementación de stacking mediante tres componentes principales:
- Modelos base (learners): Modelos individuales que se entrenan y cuyas predicciones se combinan (ej.:
SL.lm,SL.glmnet,SL.ranger,SL.xgboost). - Meta-learner: Un modelo final que aprende a combinar las predicciones de los modelos base. Puede ser una regresión lineal, nnls (Non-Negative Least Squares) o un modelo más complejo.
- Validación cruzada interna: Super Learner divide los datos en múltiples subconjuntos para estimar el rendimiento de cada modelo antes de combinarlos.
12.3. Implementación en NHANES: Predicción de la Presión Arterial
📌 Paso 1: Cargar paquetes y la base de datos NHANES
# Instalar y cargar librerías necesarias
install.packages(c("SuperLearner", "tidyverse", "nhanesA", "glmnet", "ranger", "xgboost"))
library(SuperLearner)
library(tidyverse)
library(nhanesA)
library(glmnet)
library(ranger)
library(xgboost)
# Descargar y preparar la base de datos NHANES
df <- nhanes("BPX") # Extraer datos de presión arterial
# Seleccionar variables de interés
df <- df %>%
select(BPXDI1, Age, Gender, BMI, Race) %>%
drop_na() # Eliminar valores faltantes
# Definir variable respuesta y predictores
Y <- df$BPXDI1 # Presión arterial diastólica
X <- df %>% select(-BPXDI1) # Variables predictoras📌 Paso 2: Definir los modelos base (learners)
SLlist <- c("SL.lm", "SL.glmnet", "SL.ranger", "SL.xgboost")📌 Paso 3: Entrenar el Super Learner
set.seed(123)
SLres <- SuperLearner(
Y = Y,
X = X,
SL.library = SLlist,
family = gaussian()
)
print(SLres)📌 Paso 4: Analizar la combinación de modelos
El resultado mostrará los pesos asignados a cada modelo. Si un modelo tiene un peso alto, significa que contribuyó más a la predicción final.
12.4. Ajuste de Hiperparámetros en los Modelos Base
Podemos mejorar el rendimiento de los modelos base ajustando sus hiperparámetros antes de combinarlos en el Super Learner.
📌 Ejemplo: Ajustando Hiperparámetros en LASSO y Random Forest
# Crear versiones personalizadas de modelos base con hiperparámetros ajustados
SL.lasso <- create.Learner("SL.glmnet", tune = list(alpha = 1, lambda = 0.01))
SL.rf <- create.Learner("SL.ranger", tune = list(num.trees = 500, mtry = 2))
# Definir nuevo conjunto de learners
SLlist_tuned <- c(SL.lasso$names, SL.rf$names, "SL.xgboost")
# Entrenar el Super Learner con modelos ajustados
set.seed(123)
SLres_tuned <- SuperLearner(
Y = Y,
X = X,
SL.library = SLlist_tuned,
family = gaussian()
)
print(SLres_tuned)12.5. Evaluación del Super Learner con Validación Cruzada
Para estimar el error de generalización, usamos validación cruzada con CV.SuperLearner.
SLcv <- CV.SuperLearner(
Y = Y,
X = X,
SL.library = SLlist_tuned,
family = gaussian(),
cvControl = list(V = 5) # 5-fold CV
)
# Calcular el Error Cuadrático Medio (MSE) del Super Learner
mse <- mean((Y - SLcv$SL.predict)^2)
print(mse)Un MSE más bajo indica un mejor ajuste del modelo.
12.6. Meta-Learner con nnls
El meta-learner aprende a combinar las predicciones de los modelos base. Uno de los más usados es nnls (Non-Negative Least Squares), que impone restricciones de coeficientes positivos.
SLres_nnls <- SuperLearner(
Y = Y,
X = X,
SL.library = SLlist_tuned,
method = "method.NNLS",
family = gaussian()
)
print(SLres_nnls)Conclusiones y Reflexión Final
✅ Super Learner combina múltiples modelos para mejorar la precisión predictiva.
✅ Ajustar hiperparámetros en modelos base mejora su rendimiento dentro del ensamble.
✅ El meta-learner optimiza la combinación de predicciones, y nnls garantiza coeficientes no negativos.
✅ La validación cruzada con CV.SuperLearner permite estimar la capacidad predictiva del modelo.
🎓 ¡Felicidades! Has completado el Módulo 12.
Módulo 13: Ejemplo Completo Integrado (Desde EDA hasta SuperLearner)
Este módulo tiene como objetivo consolidar los conocimientos adquiridos en el curso aplicando todo el flujo de análisis, desde la exploración de datos hasta la creación de un modelo predictivo utilizando SuperLearner. Se usará la base de datos NHANES.
13.1. Carga y Exploración de los Datos
1. Importar librerías y datos
# Instalar y cargar librerías necesarias
install.packages(c("tidyverse", "nhanesA", "DataExplorer", "skimr", "gtsummary", "SuperLearner"))
library(tidyverse)
library(nhanesA)
library(DataExplorer)
library(skimr)
library(gtsummary)
library(SuperLearner)
# Cargar datos desde NHANES
nhanes_data <- nhanes("BPX")2. Seleccionar y revisar las variables de interés
# Selección de variables relevantes
nhanes_df <- nhanes_data %>%
select(BPXDI1, Age, Gender, BMI, Race, Diabetes) %>%
drop_na()
# Estructura y resumen de los datos
str(nhanes_df)
skim(nhanes_df)
create_report(nhanes_df)13.2. Preprocesamiento de Datos
3. Conversión de variables categóricas
nhanes_df <- nhanes_df %>%
mutate(Gender = as.factor(Gender),
Race = as.factor(Race),
Diabetes = as.factor(Diabetes))4. Análisis de valores faltantes
plot_missing(nhanes_df)5. Análisis Descriptivo
nhanes_df %>%
tbl_summary(by = Gender) %>%
add_overall() %>%
add_p()13.3. Visualización de Datos con ggplot2
6. Distribución de la Presión Arterial
ggplot(nhanes_df, aes(x = BPXDI1)) +
geom_histogram(bins = 30, fill = "steelblue", color = "black") +
labs(title = "Distribución de la Presión Arterial Diastólica")7. Relación entre Edad y Presión Arterial
ggplot(nhanes_df, aes(x = Age, y = BPXDI1)) +
geom_point(alpha = 0.5) +
geom_smooth(method = "lm", se = FALSE, color = "red") +
labs(title = "Relación entre Edad y Presión Arterial")13.4. Modelado Estadístico
8. Regresión Lineal
mod_lin <- lm(BPXDI1 ~ Age + BMI + Gender + Race, data = nhanes_df)
summary(mod_lin)9. Regresión Logística (Diabetes)
mod_logit <- glm(Diabetes ~ Age + BMI + Gender + Race, data = nhanes_df, family = binomial)
tbl_regression(mod_logit, exponentiate = TRUE)13.5. Introducción a Machine Learning y Super Learner
10. Definición de Modelos Base
SLlist <- c("SL.lm", "SL.glmnet", "SL.ranger", "SL.xgboost")11. Creación del Super Learner
set.seed(123)
SLres <- SuperLearner(
Y = nhanes_df$BPXDI1,
X = nhanes_df %>% select(-BPXDI1),
SL.library = SLlist,
family = gaussian()
)
print(SLres)12. Validación Cruzada del Super Learner
SLcv <- CV.SuperLearner(
Y = nhanes_df$BPXDI1,
X = nhanes_df %>% select(-BPXDI1),
SL.library = SLlist,
family = gaussian(),
cvControl = list(V = 5)
)
# Calcular MSE
mse <- mean((nhanes_df$BPXDI1 - SLcv$SL.predict)^2)
print(mse)13.6. Reflexión Final
- ¿Qué modelo tuvo el mejor desempeño? Comparar el error del Super Learner con los modelos individuales.
- ¿Qué otras variables podrían mejorar el modelo? Identificar posibles predictores adicionales.
- ¿Cómo podríamos mejorar el ajuste del modelo? Ajuste de hiperparámetros y selección de mejores learners.
🚀📊 “Felicidades por completar este viaje a través de la epidemiología avanzada con R. Ahora tienes las herramientas para explorar datos, construir modelos y tomar decisiones basadas en evidencia. ¡El conocimiento solo crece cuando se aplica, así que sigue explorando, analizando y creando!” 🚀📊