R
Tutorial R: Estructuras de control condicional
Aprende a usar estructuras condicionales en R como if-else, ifelse, switch y case_when para controlar el flujo y analizar datos eficientemente.
Aprende R y certifícateif-else: sintaxis y evaluación de condiciones
Las estructuras condicionales son fundamentales en cualquier lenguaje de programación, ya que permiten que nuestro código tome decisiones basadas en ciertas condiciones. En R, la estructura condicional básica es if-else
, que nos permite ejecutar bloques de código diferentes dependiendo de si una condición se cumple o no.
Estructura básica de if-else
La sintaxis básica de una estructura if-else
en R es la siguiente:
if (condición) {
# Código que se ejecuta si la condición es TRUE
} else {
# Código que se ejecuta si la condición es FALSE
}
Veamos un ejemplo sencillo:
temperatura <- 25
if (temperatura > 30) {
print("Hace calor")
} else {
print("No hace tanto calor")
}
En este ejemplo, como la temperatura es 25 (menor que 30), se imprimirá "No hace tanto calor".
Evaluación de condiciones
La condición dentro del paréntesis de if
debe ser una expresión que se evalúe como un valor lógico (TRUE
o FALSE
). R ofrece varios operadores para construir estas condiciones:
- Operadores de comparación:
==
(igual a)!=
(distinto de)>
(mayor que)<
(menor que)>=
(mayor o igual que)<=
(menor o igual que)
edad <- 18
if (edad >= 18) {
print("Eres mayor de edad")
} else {
print("Eres menor de edad")
}
- Operadores lógicos para combinar condiciones:
&
(AND lógico)|
(OR lógico)!
(NOT lógico)
edad <- 25
tiene_carnet <- TRUE
if (edad >= 18 & tiene_carnet) {
print("Puedes conducir")
} else {
print("No puedes conducir")
}
Uso de if sin else
También podemos usar if
sin necesidad de incluir un else
:
nota <- 9
if (nota >= 9) {
print("¡Excelente trabajo!")
}
En este caso, si la condición no se cumple, simplemente no se ejecuta ningún código adicional.
Estructuras if-else-if
Cuando necesitamos evaluar múltiples condiciones en secuencia, podemos encadenar varias estructuras if-else
:
nota <- 7.5
if (nota >= 9) {
print("Sobresaliente")
} else if (nota >= 7) {
print("Notable")
} else if (nota >= 5) {
print("Aprobado")
} else {
print("Suspenso")
}
En este ejemplo, como la nota es 7.5, se imprimirá "Notable". El programa evalúa cada condición en orden y ejecuta el bloque correspondiente a la primera condición que se cumple.
Condiciones anidadas
También podemos anidar estructuras condicionales, es decir, incluir un if-else
dentro de otro:
edad <- 25
ingresos <- 2000
if (edad >= 18) {
if (ingresos > 1000) {
print("Puedes solicitar el préstamo")
} else {
print("Eres mayor de edad pero tus ingresos son insuficientes")
}
} else {
print("Debes ser mayor de edad para solicitar un préstamo")
}
Consideraciones importantes
- Valores NA: Ten cuidado con los valores
NA
(datos faltantes) en las condiciones, ya que pueden causar comportamientos inesperados:
x <- NA
if (x > 10) { # Esto dará un warning y el resultado será NA
print("x es mayor que 10")
} else {
print("x no es mayor que 10")
}
Para manejar valores NA
correctamente, puedes usar la función is.na()
:
x <- NA
if (is.na(x)) {
print("x es NA")
} else if (x > 10) {
print("x es mayor que 10")
} else {
print("x es menor o igual a 10")
}
- Condiciones vectorizadas: La estructura
if-else
estándar en R está diseñada para trabajar con una única condición lógica (un valorTRUE
oFALSE
), no con vectores de condiciones:
numeros <- c(5, 15, 25)
# Esto generará un warning porque if espera una única condición
if (numeros > 10) {
print("Mayor que 10")
}
Este código generará un warning porque if
solo evalúa el primer elemento del vector. Para operaciones con vectores completos, necesitarás usar funciones vectorizadas como ifelse()
, que veremos en la siguiente sección.
Ejemplo práctico: Análisis de datos
Veamos un ejemplo más completo donde usamos condicionales para analizar un dato:
analizar_temperatura <- function(temp) {
if (is.na(temp)) {
return("Dato faltante")
}
if (temp < 0) {
return("Temperatura bajo cero")
} else if (temp < 15) {
return("Temperatura fría")
} else if (temp < 25) {
return("Temperatura agradable")
} else {
return("Temperatura calurosa")
}
}
# Probamos la función
analizar_temperatura(22) # "Temperatura agradable"
analizar_temperatura(-5) # "Temperatura bajo cero"
En este ejemplo, hemos creado una función que analiza un valor de temperatura y devuelve una descripción según su valor. La función primero verifica si el dato es NA
y luego evalúa diferentes rangos de temperatura.
Buenas prácticas
- Usa llaves
{}
incluso para bloques de una sola línea, mejora la legibilidad y evita errores. - Indenta correctamente tu código para que sea más fácil de leer.
- Simplifica las condiciones complejas dividiéndolas en variables intermedias con nombres descriptivos.
- Evita anidar demasiados niveles de
if-else
, ya que puede hacer que el código sea difícil de seguir.
# En lugar de:
if (edad >= 18 & ingresos > 1000 & !tiene_deudas) {
print("Préstamo aprobado")
}
# Mejor así:
es_mayor_edad <- edad >= 18
tiene_ingresos_suficientes <- ingresos > 1000
esta_libre_deudas <- !tiene_deudas
if (es_mayor_edad & tiene_ingresos_suficientes & esta_libre_deudas) {
print("Préstamo aprobado")
}
Las estructuras if-else
son la base para implementar la lógica condicional en R. Aunque son potentes para decisiones simples, cuando necesitamos aplicar condiciones a vectores completos o manejar múltiples casos, existen alternativas más eficientes que veremos en las siguientes secciones.
ifelse(): vectorización de condicionales
Cuando trabajamos con vectores en R, la estructura if-else
tradicional presenta limitaciones importantes, ya que solo evalúa el primer elemento del vector. Para aplicar condiciones a todos los elementos de un vector simultáneamente, R ofrece la función ifelse()
, que es una versión vectorizada de la estructura condicional.
La función ifelse()
evalúa una condición para cada elemento de un vector y devuelve un nuevo vector con los resultados correspondientes. Su sintaxis básica es:
ifelse(condición, valor_si_verdadero, valor_si_falso)
Funcionamiento básico
Veamos un ejemplo sencillo para entender cómo funciona:
# Vector de temperaturas
temperaturas <- c(5, 15, 25, 35)
# Clasificar cada temperatura
clasificacion <- ifelse(temperaturas > 20, "Calor", "Frío")
print(clasificacion)
Este código produce:
[1] "Frío" "Frío" "Calor" "Calor"
La función ifelse()
evalúa la condición temperaturas > 20
para cada elemento del vector y crea un nuevo vector con "Calor" donde la condición es verdadera y "Frío" donde es falsa.
Comparación con if-else tradicional
Para apreciar mejor la diferencia, comparemos cómo procesaríamos un vector con ambos enfoques:
# Vector de números
numeros <- c(2, 7, 4, 9, 1)
# Enfoque con bucle y if-else tradicional
resultado1 <- numeric(length(numeros))
for (i in 1:length(numeros)) {
if (numeros[i] > 5) {
resultado1[i] <- numeros[i] * 2
} else {
resultado1[i] <- numeros[i] / 2
}
}
# Enfoque vectorizado con ifelse()
resultado2 <- ifelse(numeros > 5, numeros * 2, numeros / 2)
print(resultado1)
print(resultado2)
Ambos enfoques producen el mismo resultado, pero el código con ifelse()
es más conciso y generalmente más eficiente en R, especialmente para vectores grandes.
Manejo de valores NA
Una ventaja importante de ifelse()
es que maneja correctamente los valores NA
:
# Vector con valores NA
edades <- c(25, NA, 17, 30, NA)
# Clasificar como "Adulto" o "Menor" (los NA se mantienen como NA)
clasificacion <- ifelse(edades >= 18, "Adulto", "Menor")
print(clasificacion)
Resultado:
[1] "Adulto" NA "Menor" "Adulto" NA
Si queremos tratar los valores NA
de forma específica, podemos combinar ifelse()
con is.na()
:
# Tratar los NA como "Desconocido"
clasificacion_completa <- ifelse(is.na(edades), "Desconocido",
ifelse(edades >= 18, "Adulto", "Menor"))
print(clasificacion_completa)
Resultado:
[1] "Adulto" "Desconocido" "Menor" "Adulto" "Desconocido"
Operaciones con vectores
La función ifelse()
permite realizar operaciones diferentes según la condición:
# Vector de valores
valores <- c(-3, 0, 4, -2, 7)
# Aplicar operaciones diferentes según el signo
resultado <- ifelse(valores < 0, valores^2, sqrt(valores))
print(resultado)
Resultado:
[1] 9.000000 0.000000 2.000000 4.000000 2.645751
En este ejemplo, elevamos al cuadrado los valores negativos y calculamos la raíz cuadrada de los no negativos.
Condiciones múltiples con ifelse() anidados
Podemos anidar llamadas a ifelse()
para manejar múltiples condiciones:
# Vector de notas
notas <- c(3.5, 6.7, 9.2, 4.8, 7.5)
# Clasificar en diferentes categorías
calificaciones <- ifelse(notas >= 9, "Sobresaliente",
ifelse(notas >= 7, "Notable",
ifelse(notas >= 5, "Aprobado", "Suspenso")))
print(calificaciones)
Resultado:
[1] "Suspenso" "Aprobado" "Sobresaliente" "Suspenso" "Notable"
Sin embargo, para múltiples condiciones, existen alternativas más legibles como case_when()
que veremos en la siguiente sección.
Aplicaciones prácticas
La función ifelse()
es especialmente útil en el análisis de datos y la transformación de variables:
# Datos de ingresos mensuales
ingresos <- c(1200, 2500, 800, 3000, 1500)
# Calcular impuestos con diferentes tasas según el nivel de ingresos
impuestos <- ifelse(ingresos > 2000, ingresos * 0.25, ingresos * 0.15)
print(impuestos)
Resultado:
[1] 180.0 625.0 120.0 750.0 225.0
También es útil para recodificar variables en análisis estadísticos:
# Datos categóricos codificados numéricamente
genero_codigo <- c(1, 2, 1, 1, 2, 2)
# Convertir a etiquetas más descriptivas
genero_etiqueta <- ifelse(genero_codigo == 1, "Hombre", "Mujer")
print(genero_etiqueta)
Rendimiento y consideraciones
La función ifelse()
es generalmente más eficiente que los bucles con if-else
para vectores grandes, pero tiene algunas limitaciones:
- Puede ser más lenta que otras funciones vectorizadas nativas de R para operaciones muy simples.
- Con múltiples condiciones anidadas, el código puede volverse difícil de leer.
- En algunos casos, puede cambiar la clase de los datos de forma inesperada.
# Ejemplo de cambio de clase
x <- as.Date("2023-01-15")
y <- ifelse(TRUE, x, x)
class(x) # "Date"
class(y) # "numeric" - ¡La clase ha cambiado!
Para preservar clases especiales como fechas o factores, a veces es mejor usar alternativas como dplyr::if_else()
del paquete dplyr, que es más estricta con los tipos de datos.
Ejemplo integrado
Veamos un ejemplo más completo que integra varios conceptos:
# Datos de estudiantes
edades <- c(19, 17, 22, 16, 25, NA)
puntuaciones <- c(85, 92, 78, 63, NA, 88)
# Crear una clasificación combinando múltiples condiciones
resultado <- ifelse(is.na(edades) | is.na(puntuaciones), "Datos incompletos",
ifelse(edades >= 18 & puntuaciones >= 70, "Aprobado con requisitos",
ifelse(puntuaciones >= 70, "Aprobado pero menor de edad",
"No cumple requisitos")))
print(resultado)
Este ejemplo muestra cómo ifelse()
nos permite aplicar lógica condicional compleja a vectores completos de manera eficiente, una capacidad fundamental para el análisis de datos en R.
switch() y case_when() para múltiples condiciones
Cuando necesitamos manejar múltiples condiciones en R, las estructuras anidadas de if-else
o ifelse()
pueden volverse difíciles de leer y mantener. Para estos casos, R ofrece alternativas más elegantes y legibles: la función switch()
y case_when()
del paquete dplyr.
La función switch()
La función switch()
es ideal para situaciones donde necesitamos seleccionar un valor basado en una expresión que puede tomar varios valores discretos. Es especialmente útil cuando queremos evitar largas cadenas de if-else
.
La sintaxis básica de switch()
es:
switch(expresión, valor1, valor2, ..., valorN)
Donde la expresión determina qué valor se devuelve:
# Ejemplo básico con valores numéricos
dia_numero <- 3
dia_nombre <- switch(dia_numero,
"Lunes",
"Martes",
"Miércoles",
"Jueves",
"Viernes",
"Sábado",
"Domingo")
print(dia_nombre) # "Miércoles"
En este ejemplo, como dia_numero
es 3, switch()
devuelve el tercer valor de la lista.
Uso con expresiones de caracteres
Una forma más clara de usar switch()
es con expresiones de caracteres, donde los nombres de los argumentos actúan como casos:
# Ejemplo con expresión de caracteres
fruta <- "manzana"
color <- switch(fruta,
manzana = "rojo",
plátano = "amarillo",
naranja = "naranja",
uva = "morado",
"desconocido") # valor por defecto
print(color) # "rojo"
Si la expresión no coincide con ningún caso, switch()
devuelve NULL
o el último argumento sin nombre (si existe):
fruta <- "kiwi"
color <- switch(fruta,
manzana = "rojo",
plátano = "amarillo",
naranja = "naranja",
"color desconocido") # valor por defecto
print(color) # "color desconocido"
Casos con múltiples instrucciones
Cada caso en switch()
puede contener múltiples instrucciones si las encerramos entre llaves:
operacion <- "suma"
a <- 5
b <- 3
resultado <- switch(operacion,
suma = {
cat("Sumando", a, "y", b, "\n")
a + b
},
resta = {
cat("Restando", b, "de", a, "\n")
a - b
},
multiplicacion = a * b,
division = a / b,
"Operación no válida")
print(resultado) # Imprime "Sumando 5 y 3" y luego 8
Limitaciones de switch()
Aunque switch()
es útil, tiene algunas limitaciones:
- No está vectorizado, por lo que no funciona con vectores de expresiones.
- No permite condiciones complejas para los casos.
- Requiere valores discretos y exactos para la expresión.
La función case_when()
Para situaciones más complejas, especialmente cuando trabajamos con vectores y necesitamos evaluar múltiples condiciones, la función case_when()
del paquete dplyr ofrece una solución más flexible y potente.
Primero, necesitamos cargar el paquete dplyr:
# Cargar el paquete dplyr
library(dplyr)
La sintaxis básica de case_when()
es:
case_when(
condición1 ~ resultado1,
condición2 ~ resultado2,
...
TRUE ~ resultado_por_defecto
)
Cada condición se evalúa en orden, y se devuelve el resultado correspondiente a la primera condición que se cumple:
# Vector de notas
notas <- c(3.5, 6.7, 9.2, 4.8, 7.5)
# Clasificar notas con case_when()
calificaciones <- case_when(
notas >= 9 ~ "Sobresaliente",
notas >= 7 ~ "Notable",
notas >= 5 ~ "Aprobado",
TRUE ~ "Suspenso" # Condición por defecto
)
print(calificaciones)
Resultado:
[1] "Suspenso" "Aprobado" "Sobresaliente" "Suspenso" "Notable"
Ventajas de case_when()
La función case_when()
ofrece varias ventajas importantes:
- Es vectorizada, por lo que funciona con vectores completos.
- Permite condiciones complejas en cada caso.
- Es más legible que múltiples
ifelse()
anidados. - Mantiene los tipos de datos de manera consistente.
Manejo de valores NA
case_when()
maneja los valores NA
de forma explícita:
# Vector con valores NA
edades <- c(25, NA, 17, 30, NA)
# Clasificar edades tratando NA de forma específica
clasificacion <- case_when(
is.na(edades) ~ "Desconocido",
edades >= 18 ~ "Adulto",
edades < 18 ~ "Menor"
)
print(clasificacion)
Resultado:
[1] "Adulto" "Desconocido" "Menor" "Adulto" "Desconocido"
Condiciones no mutuamente excluyentes
Con case_when()
, el orden de las condiciones es importante cuando no son mutuamente excluyentes:
# Vector de valores
valores <- c(-5, 0, 10, 15, 25)
# Clasificar valores con condiciones que se solapan
clasificacion <- case_when(
valores > 20 ~ "Muy alto",
valores > 10 ~ "Alto",
valores > 0 ~ "Positivo",
valores == 0 ~ "Cero",
TRUE ~ "Negativo"
)
print(clasificacion)
Resultado:
[1] "Negativo" "Cero" "Positivo" "Alto" "Muy alto"
Combinación de múltiples condiciones
case_when()
permite combinar múltiples condiciones con operadores lógicos:
# Datos de personas
edades <- c(15, 25, 17, 30, 22)
ingresos <- c(0, 1500, 500, 3000, 1200)
# Clasificar según múltiples variables
categoria <- case_when(
edades < 18 & ingresos > 0 ~ "Menor trabajador",
edades < 18 & ingresos == 0 ~ "Menor dependiente",
edades >= 18 & ingresos > 2000 ~ "Adulto ingresos altos",
edades >= 18 & ingresos > 0 ~ "Adulto ingresos normales",
TRUE ~ "Caso no contemplado"
)
print(categoria)
Resultado:
[1] "Menor dependiente" "Adulto ingresos normales" "Menor trabajador"
[4] "Adulto ingresos altos" "Adulto ingresos normales"
Comparación entre switch() y case_when()
Para entender mejor cuándo usar cada función, veamos una comparación directa:
switch() es ideal para:
Seleccionar entre opciones basadas en un único valor discreto
Casos simples con pocas opciones
Situaciones no vectorizadas (un solo valor)
case_when() es mejor para:
Operaciones vectorizadas (aplicar a múltiples valores)
Condiciones complejas o solapadas
Situaciones que requieren evaluación de múltiples variables
Ejemplo comparativo
Supongamos que queremos clasificar días de la semana:
# Con switch() - para un solo valor
dia <- "martes"
tipo_dia <- switch(dia,
lunes = "Inicio de semana",
martes = "Día laborable",
miércoles = "Mitad de semana",
jueves = "Día laborable",
viernes = "Fin de semana laboral",
sábado = "Fin de semana",
domingo = "Fin de semana",
"Día no válido")
print(tipo_dia) # "Día laborable"
# Con case_when() - para múltiples valores
dias <- c("lunes", "miércoles", "viernes", "domingo", "hola")
tipo_dias <- case_when(
dias %in% c("lunes") ~ "Inicio de semana",
dias %in% c("martes", "jueves") ~ "Día laborable",
dias %in% c("miércoles") ~ "Mitad de semana",
dias %in% c("viernes") ~ "Fin de semana laboral",
dias %in% c("sábado", "domingo") ~ "Fin de semana",
TRUE ~ "Día no válido"
)
print(tipo_dias)
Resultado de tipo_dias
:
[1] "Inicio de semana" "Mitad de semana" "Fin de semana laboral" "Fin de semana"
[5] "Día no válido"
Ejemplo práctico: Análisis de datos
Veamos un ejemplo más completo donde usamos case_when()
para analizar un conjunto de datos:
# Datos de estudiantes
estudiantes <- data.frame(
nombre = c("Ana", "Carlos", "Elena", "David", "Sofía"),
edad = c(16, 19, 17, 22, 20),
nota_matematicas = c(8.5, 6.2, 9.1, 5.5, 7.8),
nota_lengua = c(7.2, 8.0, 8.5, 6.0, 9.2),
asistencia = c(90, 75, 95, 60, 85)
)
# Añadir clasificaciones usando case_when()
estudiantes$rendimiento <- case_when(
estudiantes$nota_matematicas >= 8 & estudiantes$nota_lengua >= 8 ~ "Excelente",
estudiantes$nota_matematicas >= 7 | estudiantes$nota_lengua >= 7 ~ "Bueno",
estudiantes$nota_matematicas >= 5 & estudiantes$nota_lengua >= 5 ~ "Suficiente",
TRUE ~ "Insuficiente"
)
estudiantes$estado <- case_when(
estudiantes$edad < 18 ~ "Menor",
estudiantes$edad >= 18 ~ "Adulto"
)
estudiantes$asistencia_clasificacion <- case_when(
estudiantes$asistencia >= 90 ~ "Excelente",
estudiantes$asistencia >= 80 ~ "Buena",
estudiantes$asistencia >= 70 ~ "Regular",
TRUE ~ "Deficiente"
)
print(estudiantes)
Este ejemplo muestra cómo case_when()
nos permite crear fácilmente nuevas variables categóricas basadas en múltiples condiciones, una tarea común en el análisis de datos.
Buenas prácticas
Al trabajar con switch()
y case_when()
, considera estas recomendaciones:
- Usa
switch()
para casos simples basados en un único valor discreto. - Prefiere
case_when()
para condiciones complejas o vectorizadas. - Ordena las condiciones en
case_when()
de más específicas a más generales. - Incluye siempre una condición por defecto (
TRUE ~ valor
) encase_when()
. - Mantén la consistencia en los tipos de datos devueltos por cada caso.
- Usa comentarios para explicar condiciones complejas.
Estas funciones te permitirán escribir código más limpio y mantenible cuando trabajes con múltiples condiciones en R, evitando las estructuras anidadas que pueden volverse difíciles de leer y depurar.
Otros ejercicios de programación de R
Evalúa tus conocimientos de esta lección Estructuras de control condicional con nuestros retos de programación de tipo Test, Puzzle, Código y Proyecto con VSCode, guiados por IA.
Todas las lecciones de R
Accede a todas las lecciones de R y aprende con ejemplos prácticos de código y ejercicios de programación con IDE web sin instalar nada.
Instalación De R Y Rstudio
Introducción Y Entorno
Introducción A R
Introducción Y Entorno
Operadores
Sintaxis
Estructuras De Datos
Sintaxis
Funciones
Sintaxis
Estructuras De Control Iterativo
Sintaxis
Scopes Y Closures
Sintaxis
Estructuras De Control Condicional
Sintaxis
Funciones Anónimas
Sintaxis
Tipos De Datos Y Variables
Sintaxis
Sistema R6: Clases Referenciales Y Encapsulamiento
Programación Orientada A Objetos
Sistema S4: Clases Formales Y Validación
Programación Orientada A Objetos
Herencia Y Polimorfismo En R
Programación Orientada A Objetos
Sistemas De Oop En R
Programación Orientada A Objetos
Sistema S3: Clases Implícitas Y Métodos Genéricos
Programación Orientada A Objetos
Tidyverse Para Transformación De Datos
Manipulación De Datos
Lubridate Para Fechas Y Tiempo
Manipulación De Datos
Group_by Y Summarize Para Agrupación Y Resumen
Manipulación De Datos
Stringr Para Expresiones Regulares
Manipulación De Datos
Tidyr Para Limpieza De Valores Faltantes
Manipulación De Datos
Joins En R Para Combinación Y Relaciones De Tablas
Manipulación De Datos
Pivot_longer Y Pivot_wider Para Reestructuración
Manipulación De Datos
Mutate Y Transmute Para Transformación
Manipulación De Datos
Dplyr Para Filtrado Y Selección
Manipulación De Datos
Readr Y Read.csv Para Importar Datos
Manipulación De Datos
Gráficos Bivariantes En R
Visualización De Datos
Gráficos Univariantes En R
Visualización De Datos
Facetas En Ggplot2
Visualización De Datos
Personalización Y Temas
Visualización De Datos
Ggplot2 Para Visualización De Datos
Visualización De Datos
Gráficos Multivariantes En R
Visualización De Datos
Correlación En R
Estadística
Regresión Lineal En R
Estadística
Pruebas De Hipótesis En R
Estadística
Anova En R
Estadística
Estadística Descriptiva En R
Estadística
En esta lección
Objetivos de aprendizaje de esta lección
- Comprender la sintaxis y funcionamiento básico de las estructuras if-else en R.
- Aprender a evaluar condiciones lógicas y combinar operadores de comparación y lógicos.
- Diferenciar entre el uso de if-else tradicional y la función vectorizada ifelse() para trabajar con vectores.
- Conocer las funciones switch() y case_when() para manejar múltiples condiciones de forma legible y eficiente.
- Aplicar buenas prácticas en la escritura de condicionales para mejorar la legibilidad y mantenimiento del código.