Automatización: funciones, condicionales y simulación
Universidad El Bosque
11 de junio de 2026
ifelse() y case_when()fauxParte 1
Funciones en R
Imagina que quieres crear el mismo histograma con una línea de media para varias variables:
ggplot(datos, aes(x = gad7)) +
geom_histogram(fill = "#225faa", bins = 22) +
geom_vline(aes(xintercept = mean(gad7)), colour = "red", linewidth = 1) +
labs(title = "GAD-7", x = "Puntaje", y = "Frecuencia") + theme_minimal()
ggplot(datos, aes(x = bienestar)) +
geom_histogram(fill = "#225faa", bins = 30) +
geom_vline(aes(xintercept = mean(bienestar)), colour = "red", linewidth = 1) +
labs(title = "Bienestar", x = "Puntaje", y = "Frecuencia") + theme_minimal()
# ... y lo mismo para horas_sueno, edad, rendimiento...Si decides cambiar el color, el número de bins o el tema, tienes que editar cada bloque por separado, y cada copia es una oportunidad para cometer un error.
Cuando escribes el mismo código más de dos veces, es momento de escribir una función.
Cuatro partes:
[1] 3.57
[1] 11.4
Actividad · 5 min
Tu primera función
Escribe una función llamada resumen_variable que reciba un vector numérico y devuelva una cadena de texto con la media y la desviación estándar redondeadas a 1 decimal, en el formato "10.0 ± 3.2". Pruébala con c(12, 7, 15, 9, 11, 14, 6).
paste0() concatena cadenas de texto sin separador: paste0("Media: ", 3.5) produce "Media: 3.5". Puedes combinar texto y números en varios puntos:
Recuerda que la función de la media es mean() y la de la desviación estándar es sd(). Es mejor que ambas incluyan na.rm = TRUE para manejar valores NA (de otro modo, si hay valores NA en el vector, el resultado también será NA). No olvides usar round() para redondear los resultados a un decimal.
Parte 2
Condicionales
if / else: lógica de una sola decisión[1] "Ansiedad severa"
if / else evalúa un solo valor. Si le pasas un vector de varios puntajes, solo evalúa el primero y lanza una advertencia.
ifelse(): la versión vectorizadaifelse() recibe tres argumentos en orden fijo:
ifelse(condición, # ① evaluada para cada elemento del vector → TRUE o FALSE
si_verdadero, # ② valor devuelto cuando la condición es TRUE
si_falso) # ③ valor devuelto cuando la condición es FALSEPor ejemplo:
[1] "No severa" "No severa" "No severa" "Severa" "No severa" "Severa"
case_when(): múltiples condicionesCuando hay más de dos categorías, ifelse() anidado se vuelve ilegible. case_when() es la alternativa:
[1] "Mínima" "Leve" "Moderada" "Severa" "Leve" "Severa"
Las condiciones se evalúan en orden: cuando una es verdadera, las siguientes se ignoran. TRUE ~ al final actúa como “todo lo demás”: siempre se evalúa como verdadero y captura cualquier valor que no coincidió con las condiciones anteriores.
Parte 1 + 2
Funciones con condicionales
El GAD-7 es una escala de ansiedad generalizada con puntaje 0–21. Los puntos de corte clínicos son:
| Puntaje | Nivel |
|---|---|
| 0–4 | Mínima |
| 5–9 | Leve |
| 10–14 | Moderada |
| 15–21 | Severa |
clasificar_ansiedad()[1] "Mínima" "Leve" "Moderada" "Severa" "Leve" "Severa"
Parte 3
¿Por qué simular datos?
Simular datos se trata de generar observaciones artificiales a partir de un modelo con propiedades conocidas o esperadas. No se trata de que lo usemos para fabricar resultados ni presentar datos falsos como reales.
Usos legítimos
Parte 4
Simulación básica con R
set.seed(): reproducibilidadR genera números aleatorios a partir de un estado interno. set.seed() fija ese estado para que la simulación sea reproducible:
Sin set.seed(), cada ejecución produce valores distintos. Con el mismo número de semilla, el resultado es idéntico. El número en sí no importa, solo que sea consistente.
| Función | Qué simula |
|---|---|
rnorm(n, mean, sd) |
Distribución normal |
runif(n, min, max) |
Distribución uniforme |
sample(x, n, replace) |
Muestra de un vector |
rbinom(n, size, prob) |
Distribución binomial |
Por ejemplo:
[1] 6.954974 9.761090 9.301039 7.548196 12.316273 9.503164
[1] 83.46921 83.00830 95.69678 94.84971 60.07300 26.18074
[1] "B" "A" "B" "C" "A" "A"
rnorm() · runif() · rbinom() — distribuciones paramétricas
set.seed(17)
data.frame(
Normal = rnorm(1000, mean = 10, sd = 3),
Uniforme = runif(1000, min = 0, max = 20),
Binomial = rbinom(1000, size = 20, prob = 0.3)
) |>
pivot_longer(everything(),
names_to = "dist", values_to = "valor"
) |>
mutate(dist = factor(dist,
levels = c("Normal", "Uniforme", "Binomial")
)) |>
ggplot(aes(x = valor, fill = dist)) +
geom_histogram(binwidth = 1, show.legend = FALSE) +
facet_wrap(~dist, scales = "free", nrow = 1) +
scale_fill_manual(values = c(
"Normal" = "#225faa", "Uniforme" = "#5b9ad5",
"Binomial" = "#7db87d"
)) +
labs(x = NULL, y = "Frecuencia") +
theme_minimal()sample() — muestrear desde un conjunto existente
data.frame simuladoRows: 200
Columns: 4
$ id <chr> "ID_001", "ID_002", "ID_003", "ID_004", "ID_005", "ID_006", "I…
$ edad <dbl> 20, 21, 27, 22, 22, 27, 23, 18, 20, 21, 26, 23, 23, 22, 20, 27…
$ puntaje <dbl> 21, 3, 19, 12, 8, 9, 15, 2, 7, 14, 7, 17, 5, 10, 6, 4, 20, 7, …
$ carrera <chr> "Medicina", "Psicología", "Enfermería", "Enfermería", "Enferme…
Parte 5
Variables correlacionadas con faux

rnorm() independienteLas variables simuladas con rnorm() por separado no tienen ninguna relación entre sí. Pero en datos reales las variables suelen estar correlacionadas: más ansiedad tiende a asociarse con menos bienestar, menos horas de sueño, etc.
Simulación independiente
set.seed(1)
ind <- data.frame(
gad7 = rnorm(500, mean = 8, sd = 5),
bienestar = rnorm(500, mean = 65, sd = 15)
)
ggplot(ind, aes(x = gad7, y = bienestar)) +
geom_point(alpha = 0.3, colour = "#225faa") +
geom_smooth(method = "lm", colour = "red", se = FALSE) +
labs(title = paste0("r = ",
round(cor(ind$gad7, ind$bienestar), 2)),
x = "GAD-7", y = "Bienestar") +
theme_minimal()Simulación con faux
set.seed(1)
cor_dat <- rnorm_multi(n = 500,
mu = c(8, 65), sd = c(5, 15),
r = -0.45, empirical = TRUE,
varnames = c("gad7", "bienestar")
)
ggplot(cor_dat, aes(x = gad7, y = bienestar)) +
geom_point(alpha = 0.3, colour = "#225faa") +
geom_smooth(method = "lm", colour = "red", se = FALSE) +
labs(title = paste0("r = ",
round(cor(cor_dat$gad7, cor_dat$bienestar), 2)),
x = "GAD-7", y = "Bienestar") +
theme_minimal()faux::rnorm_multi()El paquete faux permite especificar directamente las correlaciones entre variables:
library(faux)
datos_cor <- rnorm_multi(
n = 500,
mu = c(8, 65, 6.5), # medias
sd = c(5, 15, 1.5), # desviaciones estándar
r = c(-0.45, -0.30, 0.20), # correlaciones: gad7-bien, gad7-sueño, bien-sueño
varnames = c("gad7", "bienestar", "horas_sueno"),
empirical = FALSE # FALSE: parámetros poblacionales (por defecto)
)empirical = FALSE (por defecto) trata mu, sd y r como parámetros poblacionales: cada muestra tendrá valores ligeramente distintos por azar, igual que en datos reales. Con empirical = TRUE la muestra coincide exactamente con los valores especificados, lo que puede ser útil para ejemplos demostrativos pero no refleja la variabilidad real de un muestreo.
set.seed(42)
gad7_sim <- rnorm_multi(
n = 5000,
mu = c(8, 65, 6.5),
sd = c(5, 15, 1.5),
r = c(-0.45, -0.30, 0.20),
varnames = c("gad7", "bienestar", "horas_sueno")) |>
mutate(
gad7 = round(pmax(0, pmin(21, gad7))),
bienestar = round(pmax(0, pmin(100, bienestar))),
horas_sueno = round(pmax(3, pmin(12, horas_sueno)), 1),
carrera = sample(
c("Psicología", "Medicina", "Enfermería", "Nutrición"),
n(),
replace = TRUE),
semestre = sample(1:10, n(), replace = TRUE),
sexo = sample(
c("Mujer", "Hombre", "No binario"),
n(),
replace = TRUE, prob = c(0.60, 0.35, 0.05)
)
)Rows: 5,000
Columns: 7
$ gad7 <dbl> 12, 11, 10, 9, 8, 7, 16, 9, 11, 7, 1, 15, 9, 2, 8, 7, 4…
$ bienestar <dbl> 44, 74, 60, 55, 59, 67, 43, 67, 34, 66, 44, 31, 87, 68,…
$ horas_sueno <dbl> 7.7, 6.0, 5.9, 5.8, 7.5, 4.3, 6.8, 4.6, 7.3, 6.4, 9.4, …
$ carrera <chr> "Psicología", "Medicina", "Enfermería", "Psicología", "…
$ semestre <int> 10, 3, 9, 9, 5, 6, 8, 9, 5, 10, 7, 8, 2, 7, 4, 4, 2, 5,…
$ sexo <chr> "Mujer", "Mujer", "Hombre", "Mujer", "Hombre", "Hombre"…
$ nivel_ansiedad <chr> "Moderada", "Moderada", "Moderada", "Leve", "Leve", "Le…
Parte 5 + 1 + 2
Aplicar las funciones a los datos simulados
Aplicamos clasificar_ansiedad() con mutate() y prop_severa() directamente:
gad7_sim |>
mutate(nivel_ansiedad = factor(
nivel_ansiedad,
levels = c("Mínima", "Leve", "Moderada", "Severa")
)) |>
ggplot(aes(x = nivel_ansiedad, fill = nivel_ansiedad)) +
geom_bar() +
scale_fill_manual(
values = c(
"Mínima" = "#7db87d", "Leve" = "#f5c842",
"Moderada" = "#f0943a", "Severa" = "#c0392b"
)
) +
labs(x = "Nivel de ansiedad", y = "Frecuencia", fill = NULL) +
theme_minimal() +
theme(legend.position = "none")¿Qué tendrías que hacer para visualizar a distribución por carrera?
Actividad · 10 min
Explorar los datos simulados
sexogad7 entre carrerassueno_bajo que valga TRUE cuando horas_sueno < 6Tres preguntas antes de cerrar.
Tienes la siguiente función. ¿Qué produce resumir(c(1.5, 2.7, 3.3))?
dec2.5 (media redondeada a 1 decimal, valor por defecto)2.50 (media redondeada a 2 decimales)3 (media redondeada a 0 decimales)✓ b) Como dec tiene valor por defecto 1, llamar resumir(c(1.5, 2.7, 3.3)) es equivalente a resumir(c(1.5, 2.7, 3.3), dec = 1). La media es 2.5, que redondeada a 1 decimal da 2.5.
¿Cuál es la diferencia principal entre ifelse() y case_when()?
ifelse() solo funciona con números; case_when() con textoifelse() maneja dos opciones: verdadero y falso; case_when() permite múltiples condiciones en cadenacase_when() es más lento y solo se usa dentro de mutate()✓ b) ifelse() evalúa una condición con dos salidas posibles. case_when() encadena múltiples condiciones con sus respectivos resultados, lo que lo hace mucho más legible cuando hay más de dos categorías.
¿Para qué sirve set.seed() en una simulación?
✓ c) set.seed() fija el estado interno del generador de números aleatorios. Con la misma semilla, el código produce exactamente los mismos valores en cualquier computador, lo que hace que la simulación sea reproducible.
Antes de la próxima sesión, escribe al menos una función propia y aplícala a datos simulados o a los datos de encuesta_bruta.xlsx de la Sesión 3.
Ideas:
case_when() y grafique la distribución de categoríasSi tienes datos propios de tu trabajo o investigación, este es el momento de empezar a probar tu análisis con datos simulados antes de tocar los datos reales.
Hasta la próxima sesión
¡Gracias!
Curso de R · Universidad El Bosque · Junio 2026 · ↩︎ Sitio del curso