Material extraído del libro R para principiantes https://bookdown.org/jboscomendoza/r-principiantes4/if-else.html
if (si) es usado cuando deseamos que una operación se ejecute únicamente cuando una condición se cumple.
else (de otro modo) es usado para indicarle a R qué hacer en caso de la condición de un if no se cumpla.
Un if es la manera de decirle a R:
SI esta condición es cierta, ENTONCES haz estas operaciones. El modelo para un if es:
if(Condición) { operaciones_si_la_condición_es_TRUE }
Si la condición se cumple, es decir, es verdadera (TRUE), entonces se realizan las operaciones. En caso contrario, no ocurre nada y el código con las operaciones no es ejecutado.
Por ejemplo, le pedimos a R que nos muestre el texto “Verdadero” si la condición se cumple.
# Se cumple la condición y se muestra "verdadero"
if(4 > 3) {
"Verdadero"
}
## [1] "Verdadero"
# No se cumple la condición y no pasa nada
if(4 > 5) {
"Verdadero"
}
else complementa un if, pues indica qué ocurrirá cuando la condición no se cumple, es falsa (FALSE), en lugar de no hacer nada.
Un if con else es la manera de decirle a R:
SI esta condición es es cierta, ENTONCES haz estas operaciones, DE OTRO MODO haz estas otras operaciones. El modelo para un if con un else es:
if(condición) { operaciones_si_la_condición_es_TRUE } else { operaciones_si_la_condición_es_FALSE }
Usando los ejemplos anteriores, podemos mostrar “Falso” si no se cumple la condición, en lugar de que no ocurra nada.
# Se cumple la condición y se muestra "Verdadero"
if(4 > 3) {"Verdadero"} else {"Falso"}
## [1] "Verdadero"
# No se cumple la condición y se muestra "Falso"
if(4 > 5) {
"Verdadero"
} else {
"Falso"
}
## [1] "Falso"
La función ifelse( ) nos permite vectorizar if, else. En lugar de escribir una línea de código para cada comparación, podemos usar una sola llamada a esta función, que se aplicará a todos los elementos de un vector.
Si intentamos usar if else con un vector, se nos mostrará un error
if(1:10 < 3) {
"Verdadero"
}
## Error in if (1:10 < 3) {: the condition has length > 1
En cambio, con ifelse se nos devolverá un valor para
cada elemento de un vector en el que la condición sea TRUE,
además nos devolverá otro valor para los elementos en que la condición
sea
Esta función tiene la siguiente forma.
ifelse(vector, valor_si_TRUE, valor_si_FALSE
ifelse(1:10 < 3,"verdadero", "Falso")
## [1] "verdadero" "verdadero" "Falso" "Falso" "Falso" "Falso"
## [7] "Falso" "Falso" "Falso" "Falso"
De este modo podemos usar ifelse() para saber si los
números en un vector son pares o nones. El signo %% nos
indica el residuo de la división.
num <- 1:8
ifelse(num %% 2 == 0, "Par", "Non")
## [1] "Non" "Par" "Non" "Par" "Non" "Par" "Non" "Par"
Si tenemos mas de una condición, podemo usar la opción
else if. La sintaxis es la siguente:
if(Expresión a testear_1 {
# bloque de código 1
} else if (Expresión a testear_2){
# bloque de código 2
} else {
# bloque de código 3
}
ejemplo
x <- 0
# chequear si x es positivo, negativo o cero
if (x > 0) {
print("x es un número positivo")
} else if (x < 0) {
print("x es un número negativo")
} else {
print("x es cero")
}
## [1] "x es cero"
Se puede tener una función if else dentro de otro if else
x <- 20
# chequear si x es positivo
if (x > 0) {
# Chequear si x es par o impar
if (x %% 2 == 0) {
print("x es un número positivo par")
} else {
print("x es un número positivo impar")
}
# ejecutar si x no es positivo
} else {
# chequear si x es par o impar
if (x %% 2 == 0) {
print("x es un número negativo par")
} else {
print("x es un número negativo impar")
}
}
## [1] "x es un número positivo par"
La estructura for nos permite ejecutar un bucle (loop), realizando una operación para cada elemento de un conjunto de datos.
for(elemento in objeto) {
operacion_con_elemento
}
Con lo anterior le decimos a R:
PARA cada elemento EN un objeto, haz la siguiente operación.
Al escribir un bucle for la parte que corresponde al
elemento la podemos llamar como nosotros deseemos, pero
la parte que corresponde al objeto debe ser el nombre
de un objeto existente.
Los dos bucles siguientes son equivalentes, sólo cambia el nombre que le hemos puesto al elemento.
objeto <- 1:10
for(elemento in objeto) {
operacion_con_elemento
}
for(i in objeto) {
operacion_con_elemento
}
Tradicionalmente se usa la letra i para denotar al elemento, pero nosotros usaremos nombres más descriptivos en este capítulo.
Vamos a obtener el cuadrado de cada uno de los elementos en un vector numérico del 1 al 6, que representa las caras de un dado.
dado <- 1:6
for(cara in dado) {
dado ^ 2
}
PARA cada en dado, elevarlo al cuadrado
Notarás que al ejecutar el código anterior parece que no ha ocurrido nada. En realidad, sí se han realizado las operaciones, pero R no ha devuelto sus resultados.
Las operaciones en un for se realizan pero sus
resultados nunca son devueltos automáticamente, es necesario pedirlos de
manera explícita.
Una solución para mostrar los resultados de un bucle for
es usar la función print().
for(cara in dado) {
print(cara ^ 2)
}
## [1] 1
## [1] 4
## [1] 9
## [1] 16
## [1] 25
## [1] 36
Comprobamos que la operación ha sido realizada a cada elemento de
nuestro objeto. Sin embargo, usar print() sólo mostrará los
resultados de las operaciones en la consola, no los asignará a un
objeto.
Si deseamos asignar los resultados de un bucle for a un
objeto, usamos índices.
Aprovechamos que el primer elemento en un bucle siempre es identificado con el número 1 y que continuará realizando operaciones hasta llegar al total de elementos que hemos especificado
for(numero in 1:10) {
print(numero)
}
## [1] 1
## [1] 2
## [1] 3
## [1] 4
## [1] 5
## [1] 6
## [1] 7
## [1] 8
## [1] 9
## [1] 10
En nuestro ejemplo, pasamos por los valores de dado, cara por cara. La primera cara será igual a 1, la segunda a 2, y así sucesivamente hasta el 6.
Podemos usar estos valores para asignar cada valor resultante de nuestras operaciones a una posición específica en un vector, incluso si este está vacio.
Creamos un vector vacío, asignándole como NULL como
valor.
mi_vector <- NULL
Ejecutamos nuestro bucle.
for(cara in dado) {
mi_vector[cara] <- cara ^ 2
}
Aunque no fueron mostrados en la consola, los resultados han sido
asignados al objeto mi_vector.
Una función tiene un nombre, argumentos y un cuerpo. Las funciones definidas por el usuario son creadas usando la sigiente estructura.
nombre <- function(argumentos) {
operaciones
}
Cuando asignamos una función a un nombre decimos que hemos definido una función.
El nombre que asignamos a una función nos permite ejecutarla y hacer referencias a ella. Podemos asignar la misma función a diferentes nombres o cambiar una función a la que ya le hemos asignado un nombre. Es recomendable elegir nombres claros, no ambiguos y descriptivos.
Una vez que la función tiene nombre, podemos llamarla usando su nombre, al igua lque con las funciones por defecto de R.
Los argumentos son las variables que necesita la función para realizar sus operaciones. Aparecen entre paréntesis, separados por comas. Los valores son asignados al nombre del argumento por el usuario cada vez que ejecuta una función. Esto permite que usemos nuestras funciones en distintas situaciones con diferentes datos y especificaciones.
Los argumentos pueden ser datos, estructuras de datos, conexiones a archivos u otras funciones y todos deben tener nombres diferentes.
El cuerpo de la función contiene, entre llaves, todas las operaciones que se ejecutarán cuando la función sea llamada. El cuerpo de una función puede ser tan sencillo o complejo como nosotros deseemos, incluso podemos definir funciones dentro de una función (y definir funciones dentro de una función dentro de otra función, aunque esto se vuelve confuso rápidamente).
Si el código del cuerpo de la función tiene errores, sus operaciones no se realizarán y nos será devuelto un mensaje de error al ejecutarla. R no avisa si nuestra función va a funcionar o no hasta que intentamos correrla.
Una ventaja de usar RStudio es que nos indica errores de sintaxis en nuestro código, lo cual puede prevenir algunos errores. Sin embargo, hay alguno que no detecta, como realizar operaciones o coerciones imposibles.
Para ver esto en acción, crearemos una función sencilla para obtener el área de un cuadrilátero.
Partimos del algoritmo para calcular el área de un cuadrilátero:
lado x lado.
Podemos convertir esto a operaciones de R y asignarlas a una función
llamada area_cuad de la siguiente manera:
area_cuad <- function(lado1, lado2) {
lado1 * lado2
}
Las partes de nuestra función son:
Nombre: area_cuad.
Argumentos: lado1,
lado2. Estos son los datos que necesita la función para
calcular el área, representan el largo de los lados de un
cuadrilátero.
Cuerpo: La operación lado1 * lado2,
escrita de manera que R pueda interpretarla.
Ejecutaremos nuestra función para comprobar que funciona. Nota que lo
único que hacemos cada que la llamamos es cambiar la medida de los lados
del cuadrilátero para el que calcularemos un área, en lugar de escribir
la operación lado1 * lado2 en cada ocasión.
area_cuad(lado1 = 4, lado2 = 6)area_cuad(lado1 = 36, lado2 = 36)
En cada llamada a nuestra función estamos asignando valores distintos a los argumentos usando el signo de igual. Si no asignamos valores a un argumento, se nos mostrará un error
area_cuad(lado1 = 14)
En R, podemos especificar los argumentos por posición. El orden de los argumentos se determina cuando creamos una función.
En este caso, nosotros determinamos que el primer argumento que
recibe area_cuad es lado1 y el segundo es
lado2. Así, podemos escribir lo siguiente y obtener el
resultado esperado.
area_cuad(128, 64)
Esto es equivalente a escribir lado1 = 128, lado2 = 64 como argumentos.
Podemos crear ahora una función ligeramente más compleja para calcular el volumen de un prisma rectangular
Siguiendo la misma lógica de transformar un algoritmo a código de R, podemos crear una función con el algoritmo: arista x arista x arista.
Definimos la función area_prisma().
area_prisma <- function(arista1, arista2, arista3) {
arista1 * arista2 * arista3
}
Probemos nuestra función.
area_prisma(arista1 = 3, arista2 = 6, arista3 = 9)