Material extraído del libro R para principiantes https://bookdown.org/jboscomendoza/r-principiantes4/if-else.html

if, else

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"

ifelse

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"

if...else if...else

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"

if else anidado

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"

For

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.

Usando for

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.

funciones

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.

Nuestra primera función

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)