1 Introducción

En ciencia de datos, dominar las estructuras de control, el diseño de funciones reutilizables y el manejo de estructuras de datos (como listas) es crucial para construir análisis robustos, reproducibles y escalables. Este documento aborda tres pilares prácticos:

  1. Control de flujo (repeat, break, while, for, ifelse): permiten automatizar procesos, iterar sobre datos y tomar decisiones lógicas.
  2. Funciones: encapsulan lógica de negocio y promueven la reutilización, validación y trazabilidad del análisis.
  3. Listas: soportan estructuras jerárquicas/anidadas para representar resultados complejos (modelos, métricas, metadatos), comunes en pipelines de ML, reporting y APIs.

¿Por qué importa? En proyectos reales, rara vez ejecutamos una sola instrucción: necesitamos orquestar pasos de limpieza, transformación, modelado y evaluación. Las herramientas de este documento son la base para ello.

1.1 Objetivos de aprendizaje

  • Implementar y comprender el uso de repeat, break, while, for e ifelse en tareas típicas de análisis.
  • Diseñar funciones con contexto (salud, finanzas, educación, retail) que devuelvan objetos estructurados.
  • Modelar información compleja con listas y acceder a sus elementos para reportes o pasos posteriores del pipeline.

1.2 Requisitos

  • Conocer R básico (asignación, vectores, operaciones).
  • Tener instalado R/RStudio y poder ejecutar este Rmd.

2 Control de flujo en R y su rol en ciencia de datos

Las estructuras de control permiten automatizar tareas repetitivas (simulaciones, barridos de parámetros), validar condiciones (calidad de datos) y controlar el flujo de un pipeline.

2.1 repeat + break

# Educación: Contador de estudiantes inscritos
i <- 1
repeat {
  print(paste("Estudiante", i, "inscrito"))
  if (i == 3) break
  i <- i + 1
}
## [1] "Estudiante 1 inscrito"
## [1] "Estudiante 2 inscrito"
## [1] "Estudiante 3 inscrito"
# Finanzas: Generar reportes
reporte <- 1
repeat {
  print(paste("Generando reporte", reporte))
  if (reporte == 4) break
  reporte <- reporte + 1
}
## [1] "Generando reporte 1"
## [1] "Generando reporte 2"
## [1] "Generando reporte 3"
## [1] "Generando reporte 4"
# Salud: Control de turnos
turno <- 1
repeat {
  print(paste("Turno", turno))
  if (turno >= 5) break
  turno <- turno + 1
}
## [1] "Turno 1"
## [1] "Turno 2"
## [1] "Turno 3"
## [1] "Turno 4"
## [1] "Turno 5"
# Ciencia de datos: Simular procesos
iter <- 1
repeat {
  print(paste("Iteración", iter))
  if (iter >= 3) break
  iter <- iter + 1
}
## [1] "Iteración 1"
## [1] "Iteración 2"
## [1] "Iteración 3"
# Logística: Contar camiones en cola
camion <- 1
repeat {
  print(paste("Camión", camion, "en cola"))
  if (camion == 4) break
  camion <- camion + 1
}
## [1] "Camión 1 en cola"
## [1] "Camión 2 en cola"
## [1] "Camión 3 en cola"
## [1] "Camión 4 en cola"

2.2 while (condicional)

# Finanzas: Ahorro hasta meta
ahorro <- 0
while (ahorro < 1000) {
  ahorro <- ahorro + 200
  print(paste("Ahorro actual:", ahorro))
}
## [1] "Ahorro actual: 200"
## [1] "Ahorro actual: 400"
## [1] "Ahorro actual: 600"
## [1] "Ahorro actual: 800"
## [1] "Ahorro actual: 1000"
# Educación: Contador de tareas
tareas <- 1
while (tareas <= 3) {
  print(paste("Tarea", tareas, "realizada"))
  tareas <- tareas + 1
}
## [1] "Tarea 1 realizada"
## [1] "Tarea 2 realizada"
## [1] "Tarea 3 realizada"
# Salud: Medición hasta presión estable
presion <- 160
while (presion > 140) {
  print(paste("Presión alta:", presion))
  presion <- presion - 5
}
## [1] "Presión alta: 160"
## [1] "Presión alta: 155"
## [1] "Presión alta: 150"
## [1] "Presión alta: 145"
# Ciencia de datos: Lectura de registros
reg <- 1
while (reg <= 3) {
  print(paste("Registro", reg))
  reg <- reg + 1
}
## [1] "Registro 1"
## [1] "Registro 2"
## [1] "Registro 3"
# Logística: Carga de camión
peso_total <- 0
while (peso_total < 1000) {
  peso_total <- peso_total + 250
  print(paste("Peso acumulado:", peso_total))
}
## [1] "Peso acumulado: 250"
## [1] "Peso acumulado: 500"
## [1] "Peso acumulado: 750"
## [1] "Peso acumulado: 1000"

2.3 for (iteración definida)

# Educación: Imprimir notas
notas_vec <- c(60, 70, 80)
for (nota in notas_vec) {
  print(paste("Nota:", nota))
}
## [1] "Nota: 60"
## [1] "Nota: 70"
## [1] "Nota: 80"
# Finanzas: Calcular intereses
saldos <- c(1000, 2000, 3000)
for (saldo in saldos) {
  interes <- saldo * 0.05
  print(paste("Interés:", interes))
}
## [1] "Interés: 50"
## [1] "Interés: 100"
## [1] "Interés: 150"
# Salud: Evaluación de pacientes
pacientes_vec <- c("Juan", "Ana", "Luis")
for (pac in pacientes_vec) {
  print(paste("Paciente evaluado:", pac))
}
## [1] "Paciente evaluado: Juan"
## [1] "Paciente evaluado: Ana"
## [1] "Paciente evaluado: Luis"
# Ciencia de datos: Tipos de variables
tipos <- c("Numérica", "Categórica", "Texto")
for (tipo in tipos) {
  print(paste("Tipo detectado:", tipo))
}
## [1] "Tipo detectado: Numérica"
## [1] "Tipo detectado: Categórica"
## [1] "Tipo detectado: Texto"
# Logística: Cajas en transporte
cajas <- 1:5
for (cx in cajas) {
  print(paste("Caja entregada:", cx))
}
## [1] "Caja entregada: 1"
## [1] "Caja entregada: 2"
## [1] "Caja entregada: 3"
## [1] "Caja entregada: 4"
## [1] "Caja entregada: 5"

2.4 ifelse() (vectorizado)

# Salud: Clasificación de pacientes por edad
edades <- c(12, 18, 65, 40)
cat_edad <- ifelse(edades < 18, "Menor", "Adulto")
print(cat_edad)
## [1] "Menor"  "Adulto" "Adulto" "Adulto"
# Educación: Resultados de examen
notas_exam <- c(45, 70, 89, 92)
estado_exam <- ifelse(notas_exam >= 60, "Aprobado", "Reprobado")
print(estado_exam)
## [1] "Reprobado" "Aprobado"  "Aprobado"  "Aprobado"
# Finanzas: Riesgo de clientes por ingreso
ingresos <- c(900, 2500, 3000, 4500)
riesgo_cli <- ifelse(ingresos < 1000, "Alto", "Normal")
print(riesgo_cli)
## [1] "Alto"   "Normal" "Normal" "Normal"
# Ciencia de datos: Detección de valores NA
datos <- c(10, NA, 5, NA)
flag_na <- ifelse(is.na(datos), "Falta", "Presente")
print(flag_na)
## [1] "Presente" "Falta"    "Presente" "Falta"
# Logística: Validar capacidad de peso
pesos <- c(300, 500, 750)
validacion_peso <- ifelse(pesos <= 600, "OK", "Exceso")
print(validacion_peso)
## [1] "OK"     "OK"     "Exceso"

3 Funciones reutilizables y trazables

En ciencia de datos, encapsular pasos en funciones: - evita repetir código, - hace más fácil probar y documentar, - y favorece la reproducibilidad en equipos.

A continuación, funciones con contexto aplicado:

# Salud: Datos de un paciente
crear_paciente <- function(id, nombre, edad, presion, temperatura) {
  list(
    id = id,
    nombre = nombre,
    edad = edad,
    presion = presion,
    temperatura = temperatura,
    estado = ifelse(temperatura > 37.5, "Fiebre", "Normal")
  )
}
paciente_Laura <- crear_paciente("P001", "Laura", 35, "120/80", 38.2)
paciente_Laura
## $id
## [1] "P001"
## 
## $nombre
## [1] "Laura"
## 
## $edad
## [1] 35
## 
## $presion
## [1] "120/80"
## 
## $temperatura
## [1] 38.2
## 
## $estado
## [1] "Fiebre"
# Finanzas: Registrar transacción bancaria
registrar_transaccion <- function(id, cliente, monto, tipo) {
  list(
    id = id,
    cliente = cliente,
    monto = monto,
    tipo = tipo,
    aprobado = monto <= 5000
  )
}
tx_Juan <- registrar_transaccion("T1001", "Juan", 4800, "Transferencia")
tx_Juan
## $id
## [1] "T1001"
## 
## $cliente
## [1] "Juan"
## 
## $monto
## [1] 4800
## 
## $tipo
## [1] "Transferencia"
## 
## $aprobado
## [1] TRUE
# Retail: Generar factura de una compra
generar_factura <- function(cliente, items, precios) {
  total <- sum(precios)
  list(
    cliente = cliente,
    productos = items,
    precios = precios,
    total = total,
    estado = ifelse(total > 1000, "Alta", "Regular")
  )
}
fact_Sofia <- generar_factura("Sofía", c("Teclado", "Mouse"), c(300, 150))
fact_Sofia
## $cliente
## [1] "Sofía"
## 
## $productos
## [1] "Teclado" "Mouse"  
## 
## $precios
## [1] 300 150
## 
## $total
## [1] 450
## 
## $estado
## [1] "Regular"
# Educación: Evaluación de una tarea
evaluar_tarea <- function(estudiante, puntaje, entrega) {
  list(
    estudiante = estudiante,
    puntaje = puntaje,
    entrega = entrega,
    estado = ifelse(entrega == TRUE & puntaje >= 3.0, "Aprobado", "Reprobado")
  )
}
tarea_Andres <- evaluar_tarea("Andrés", 3.5, TRUE)
tarea_Andres
## $estudiante
## [1] "Andrés"
## 
## $puntaje
## [1] 3.5
## 
## $entrega
## [1] TRUE
## 
## $estado
## [1] "Aprobado"

4 Listas para estructuras complejas

Las listas permiten almacenar objetos heterogéneos (vectores, data.frames, listas) y son ideales para agrupar resultados de modelos, métricas, configuraciones y reportes.

# L1: Datos personales anidados
lista_persona <- list(
  nombre = "Ana",
  contacto = list(email = "ana@mail.com", telefono = "123456"),
  edad = 28
)

# L2: Estudiante con notas y evaluación
lista_estudiante <- list(
  nombre = "Luis",
  notas = c(4.5, 4.0, 3.8),
  evaluacion = list(promedio = 4.1, aprobado = TRUE)
)

# L3: Empresa
lista_empresa <- list(
  nombre = "ABC S.A.",
  ubicacion = list(pais = "Colombia", ciudad = "Bogotá"),
  empleados = 100
)

# L4: Familia
lista_familia <- list(
  padres = list("Ana", "Carlos"),
  hijos = list("Laura", "Mario")
)

# L5: Curso con estudiantes
lista_curso <- list(
  titulo = "Estadística",
  estudiantes = list(
    estudiante1 = list(nombre = "Juan", nota = 4.5),
    estudiante2 = list(nombre = "Luisa", nota = 3.9)
  )
)

# L6: Encuesta con resultados
lista_encuesta <- list(
  id = 1,
  respuestas = list(p1 = TRUE, p2 = FALSE, p3 = TRUE),
  fecha = Sys.Date()
)

# L7: Ventas por región
lista_ventas <- list(
  norte = list(enero = 1000, febrero = 1200),
  sur = list(enero = 900, febrero = 950)
)

# L8: Proyecto
lista_proyecto <- list(
  titulo = "IA aplicada",
  integrantes = list("Laura", "Carlos"),
  actividades = list(analisis = TRUE, implementacion = FALSE)
)

# L9: Resultados de modelos
lista_resultados <- list(
  modelo1 = list(r2 = 0.91, mse = 2.1),
  modelo2 = list(r2 = 0.88, mse = 2.3)
)

# L10: Estación meteorológica
lista_estacion <- list(
  nombre = "Estación A",
  lecturas = list(
    temperatura = c(22.1, 23.5, 21.8),
    humedad = c(65, 70, 60)
  ),
  coordenadas = list(lat = 4.6097, lon = -74.0817)
)

# Vista rápida
lista_persona
## $nombre
## [1] "Ana"
## 
## $contacto
## $contacto$email
## [1] "ana@mail.com"
## 
## $contacto$telefono
## [1] "123456"
## 
## 
## $edad
## [1] 28
lista_estudiante
## $nombre
## [1] "Luis"
## 
## $notas
## [1] 4.5 4.0 3.8
## 
## $evaluacion
## $evaluacion$promedio
## [1] 4.1
## 
## $evaluacion$aprobado
## [1] TRUE
lista_empresa
## $nombre
## [1] "ABC S.A."
## 
## $ubicacion
## $ubicacion$pais
## [1] "Colombia"
## 
## $ubicacion$ciudad
## [1] "Bogotá"
## 
## 
## $empleados
## [1] 100
lista_familia
## $padres
## $padres[[1]]
## [1] "Ana"
## 
## $padres[[2]]
## [1] "Carlos"
## 
## 
## $hijos
## $hijos[[1]]
## [1] "Laura"
## 
## $hijos[[2]]
## [1] "Mario"
lista_curso
## $titulo
## [1] "Estadística"
## 
## $estudiantes
## $estudiantes$estudiante1
## $estudiantes$estudiante1$nombre
## [1] "Juan"
## 
## $estudiantes$estudiante1$nota
## [1] 4.5
## 
## 
## $estudiantes$estudiante2
## $estudiantes$estudiante2$nombre
## [1] "Luisa"
## 
## $estudiantes$estudiante2$nota
## [1] 3.9
lista_encuesta
## $id
## [1] 1
## 
## $respuestas
## $respuestas$p1
## [1] TRUE
## 
## $respuestas$p2
## [1] FALSE
## 
## $respuestas$p3
## [1] TRUE
## 
## 
## $fecha
## [1] "2025-08-12"
lista_ventas
## $norte
## $norte$enero
## [1] 1000
## 
## $norte$febrero
## [1] 1200
## 
## 
## $sur
## $sur$enero
## [1] 900
## 
## $sur$febrero
## [1] 950
lista_proyecto
## $titulo
## [1] "IA aplicada"
## 
## $integrantes
## $integrantes[[1]]
## [1] "Laura"
## 
## $integrantes[[2]]
## [1] "Carlos"
## 
## 
## $actividades
## $actividades$analisis
## [1] TRUE
## 
## $actividades$implementacion
## [1] FALSE
lista_resultados
## $modelo1
## $modelo1$r2
## [1] 0.91
## 
## $modelo1$mse
## [1] 2.1
## 
## 
## $modelo2
## $modelo2$r2
## [1] 0.88
## 
## $modelo2$mse
## [1] 2.3
lista_estacion
## $nombre
## [1] "Estación A"
## 
## $lecturas
## $lecturas$temperatura
## [1] 22.1 23.5 21.8
## 
## $lecturas$humedad
## [1] 65 70 60
## 
## 
## $coordenadas
## $coordenadas$lat
## [1] 4.6097
## 
## $coordenadas$lon
## [1] -74.0817