4 Estructuras de control
Como en otros lenguajes de programación, en R existen instrucciones para controlar el flujo de ejecución de un programa. Básicamente existen dos tipos:
- Condicionales: Son instrucciones que bifurcan el flujo del programa en función de si se cumple o no una condición.
- Bucles: Son instrucciones que repiten un bloque de código un numero determinado de veces o hasta que se cumple una condición.
4.1 Estructuras condicionales
Las estructuras condicionales permiten evaluar el estado del programa y tomar decisiones sobre qué código ejecutar en función del mismo.
4.1.1 Condicionales (if
)
La principal estructura condicional comienza con la palabra reservada if
, lleva asociada expresión de tipo lógico o booleano y permite ejecutar un bloque de código dependiendo de si la evaluación de esa expresión es TRUE
o FALSE
.
if (
<exp>
) {
<código>
}
Si el resultado de evaluar la expresión <exp>
es TRUE
entonces se ejecuta el código <código>
, mientras que si es FALSE
no.
Ejemplo 4.1
<- 1
x <- 0
y if (y != 0){
print(x / y)
}
Si se desea ejecutar un bloque de código alternativo cuando no se cumpla la condición se puede añadir a continuación con la palabra reservada else
.
if (
<exp>
) {
<código 1>
} else {
<código 2>
}
En este caso, si la evaluación de la condición es TRUE
se ejecuta el código <código 1>
y si es FALSE
se ejecuta el código <código 2>
.
Ejemplo 4.2
<- 8.5
nota if (nota < 5){
print("Suspenso")
else {
} print("Aprobado")
}
[1] "Aprobado"
Se puede comprobar más de una condición encadenando otra instrucción if
tras las instrucción else
.
if (
<exp 1>
) {
<código 1>
} else if (
<exp 2>
) {
<código 2>
) {
…
} else {
<código n>
}
Cuando se encadenan múltiples condiciones de esta forma, solamente se ejecuta el bloque de código asociado a la primera condición cuya evaluación sea TRUE
. El último bloque de código solamente se ejecuta si todas las condiciones son falsas.
Ejemplo 4.3
<- 8.5
nota if (nota < 5){
print("Suspenso")
else if (nota < 7) {
} print("Aprobado")
else if (nota < 9) {
} print("Notable")
else {
} print("Sobresaliente")
}
[1] "Notable"
4.1.2 La función switch()
Otra forma de tomar decisiones sobre el código a ejecutar es la función switch
.
switch(x, l)
: Ejecuta el código del valor de la listal
cuyo nombre asociado coincide con el resultado de evaluar la expresiónx
. Si el resultado de evaluarx
no es ningún nombre de los elementos de la lista devuelveNULL
.
Ejemplo 4.4
<- "reducido"
tipo.iva <- 1000
precio <- precio * switch(tipo.iva, "superreducido" = 4, "reducido" = 10, "normal" = 21) / 100
iva iva
[1] 100
4.2 Bucles
Un bucle es una estructura que permite la repetición de un bloque de código. En R existen dos tipos de bucles, los bucles iterativos y los bucles condicionales.
4.2.1 Bucles iterativos (for
)
Lo bucles iterativos repiten un bloque de código un número determinado de veces. Comienzan por la palabra reservada for
y llevan asociado un iterador, que es una variable que recorre una secuencia de un tipo de datos compuesto, normalmente un vector o una lista. El bloque de código se ejecuta tantas veces como elementos tenga la secuencia, y en cada repetición el iterador toma como valor un elemento distinto de la secuencia.
for (
i
in
<secuencia>
) {
<código>
}
Ejemplo 4.5 A continuación se muestra varios ejemplos de uso del bucle for
.
<- c("Matemáticas", "Física", "Programación")
asignaturas for (i in asignaturas) {
print(i)
}
[1] "Matemáticas"
[1] "Física"
[1] "Programación"
for (i in 1:5) {
print(paste("El cuadrado de ", i, " es ", i^2))
}
[1] "El cuadrado de 1 es 1"
[1] "El cuadrado de 2 es 4"
[1] "El cuadrado de 3 es 9"
[1] "El cuadrado de 4 es 16"
[1] "El cuadrado de 5 es 25"
También es posible recorrer los elementos de la secuencia por posición ayudándonos de la siguiente función:
seq_along(x)
: que devuelve un vector con los enteros desde 1 hasta el número de elementos de la secuenciax
.
Ejemplo 4.6
<- c("Matemáticas", "Física", "Programación")
asignaturas for (i in seq_along(asignaturas)){
print(paste("Asignatura ", i, ":", asignaturas[i]))
}
[1] "Asignatura 1 : Matemáticas"
[1] "Asignatura 2 : Física"
[1] "Asignatura 3 : Programación"
Los bucles iterativos se utilizan habitualmente para recorrer estructuras de una dimensión como los vectores y las listas, donde se sabe de antemano el número de elementos que contiene y, por tanto, el número de iteraciones del bucle. No obstante, también se pueden recorrer estructuras de más de una dimensión, como por ejemplo matrices, utilizando varios bucles for
anidados.
Ejemplo 4.7 A continuación se muestra varios ejemplos de dos bucles for
anidados para recorrer los elementos de una matriz.
<- matrix(1:6, 2, 3)
x for (i in 1:nrow(x)) {
for (j in 1:ncol(x)){
print(x[i,j])
} }
[1] 1
[1] 3
[1] 5
[1] 2
[1] 4
[1] 6
4.2.2 Bucles condicionales (while
)
Los bucles condicionales repiten un bloque de código mientras se cumpla una condición. Comienzan con la palabra reservada while
y llevan asociada una expresión lógica, de manera que mientras la evaluación de la expresión lógica sea TRUE
se repite la ejecución del bloque de código que contiene.
while (
<condición>
) {
<código>
}
La expresión lógica <condición>
se evalúa antes de ejecutar el bloque de código y solo se ejecuta el <código>
si el resultado de la evaluación es TRUE
. Obsérvese que cuando el flujo de ejecución del programa llega al bucle while
si la condición no es cierta, el código no se ejecuta ni tan siquiera una vez.
Ejemplo 4.8
<- 5
i while (i >= 0) {
print(i)
<- i - 1
i }
[1] 5
[1] 4
[1] 3
[1] 2
[1] 1
[1] 0
4.2.3 La instrucción break
La instrucción break
se utiliza para detener un bucle y salir de él, tanto en bucles iterativos como en bucles condicionales. Normalmente se suele utilizar esta instrucción cuando se cumple una determinada condición en bloque de código del bucle y se decide parar su ejecución y salir del bucle.
Ejemplo 4.9
# Bucle que recorre los números enteros del -2 al 2 pero termina al llegar al 0.
for (i in -2:2) {
if (i == 0) {
break
} print(i)
}
[1] -2
[1] -1
4.2.4 La instrucción next
La instrucción next
se utiliza para interrumpir la ejecución del bloque de código de un bucle, pero en lugar de salir del bucle pasa a la siguiente iteración. Si se trata de un bucle iterativo el iterador pasa al siguiente elemento de la secuencia de iteración y si se trata de un bucle condicional se pasa evaluar de nuevo la condición de repetición.
:::{#exm-continuacion-bucle-next}
# Bucle que recorre los enteros del 1 al 10 pero solo imprime los números pares.
for (i in 1:10) {
if (i %% 2) {
next
}print(i)
}
[1] 2
[1] 4
[1] 6
[1] 8
[1] 10
4.3 Ejercicios
Ejercicio 4.1 Crear una función para calcular la media de un vector numérico y usarla para calcular la media del vector (1, 2, NA, 3, 4)
.
<- function(x){
media <- 0
suma <- 0
n for (i in x){
if (!is.na(i)){
<- suma + i
suma <- n + 1
n
}
}return(suma / n)
}media(c(1, 2, NA, 3, 4))
[1] 2.5
Ejercicio 4.2 Usar la función anterior para crear una función para calcular las medias de las columnas de un data frame numérico. La función debe devolver un vector con las medias de las columnas. Usarla para calcular el data frame formado por los vectores (1, 2, NA, 3, 4)
y (-1, 0, -2, 0, NA)
.
<- function(df){
medias <- NULL
medias for (i in colnames(df)){
<- c(medias, media(df[[i]]))
medias
}return(medias)
}
<- data.frame(x = c(1, 2, NA, 3, 4), y = c(-1, 0, -2, 0, NA))
df medias(df)
[1] 2.50 -0.75