Funciones que se introducen en esta sesión

En ésta sesión se introducen las siguientes funciones

  • if: es usado cuando deseamos que una operación se ejecute únicamente cuando una condición se cumple.
  • else: es un complemento de la función if, y es usado para indicarle a R qué hacer en caso de la condición de un if no se cumpla.
  • ifelse: es una función vectorizada de las instrucciones if/else y permite establecer una instrucción en caso de que una condición previamente determinada se cumpla, y otra instrucción en caso de que la condición no se cumpla.
  • for: es usado para generar ciclos un número específico de veces.
  • while: es usado para generar ciclos a partir de una condición específica.
  • repeat: es usado para generar ciclos un número indefinido de veces.
  • next: es usado para finalizar la corrida de uno de los ciclos e iniciar el siguiente.
  • break: es usado para finalizar cualquier ciclo.
  • function: es usado para crear nuevas funciones.
  • return: es usado dentro de la función function para devolver un resultado en específico.

Qué es una estructura de control?

Las estructuras de control son instrucciones que permiten controlar la forma en que se ejecutará una secuencia de comandos, puesto que dan la posibilidad de establecer funciones en el código que permitan ejecutar o no algunas secuencias de código, o ejecutar repetidamente fragmentos de código una y otra vez.

Qué es un condicional?

Los condicionales son acciones usadas en programación, que permiten que se ejecute un conjuntos de instrucciones, en función de si se cumple o no una condición establecida previamente.

Funciones condicionales en R

Existen dos funciones básicas en R que permiten establecer condiciones para la ejecución de fragmentos de código, y están dadas por las funciones if/else, ifelse.

La función if() permite ejecutar una secuencia de código basada en una condición preestablecida, y puede emplearse de dos formas diferentes. La primera, es mediante el empleo de la función if() de forma individual, que puede interpretarse como un Si se cumple la condición, entonces…”

if(<condición>) {
  # Fragmento de código que se ejecuta en caso de que la condición sea verdadera
}

La segunda, es mediante el empleo de la función if() seguido de la función else, que puede interpretarse como un Si se cumple la condición, entonces…, Si no se cumple la condición, entonces…”

if(<condición>) {
  # Fragmento de código que se ejecuta en caso de que la condición es verdadera
} else {
  # Fragmento de código que se ejecuta en caso de que la condición es falta
}

Es de anotar, que la condición que se establece dentro del paréntesis de la función if(), suele establecerse mediante el empleo de Operadores lógicos.

La estructura vista de las funciones if/else puede emplearse repetidas veces, si se desean establecer condicionales anidados, de la forma

if(<condición>) {
  # Fragmento de código que se ejecuta en caso de que la condición es verdadera
} else if(<condición>) {
  # Fragmento de código que se ejecuta en caso de que la condición inicial es falsa y la condición anidada es verdadera
} else {
  # Fragmento de código que se ejecuta en caso de que la condición inicial es falsa y la condición anidada es falsa
}

Por su parte la función ifelse() que permite vectorizar la construcción if/else, para que se aplique la condición establecida a todos y cada uno de los elementos pertenecientes a un vector. La función ifelse() posee la siguiente estructura

ifelse(<condición>, <Operación si es verdadera>, <Operación si es falsa>)}

Función if

Establezca una semilla con número \(1754\), realice la selección aleatoria de dos números entre el \(1\) y el \(10\) sin remplazo, y calcule una variable \(X\) igual a la resta entre el primero y el segundo número. Establezca un condicional que evalué la variable \(X\) e imprima el mensaje “La resta es negativa”, si se encuentra que la resta es menor a \(0\).

set.seed(1754)  # Se establece la semilla
A <- sample(x = 1:10, size = 2, replace = F)  # Se crean los dos números aleatorios
A
[1] 1 5
X <- A[1] - A[2]  # Se realiza la resta del primer dato menos el segundo
X
[1] -4
# Se crea el condicional
if (X < 0) {
    print("La resta es negativa")
}
[1] "La resta es negativa"

Función if/else

Establezca una semilla con número \(143\), realice la selección aleatoria de un número entre el \(-10\) y el \(10\), sin incluir el \(0\). Si el número generado es positivo imprima el mensaje “El número generado es positivo e igual a” seguido del número generado, en caso de que no se cumpla la condición, imprima el mensaje “El número generado es negativo e igual a” seguido del número.

set.seed(143)  # Se establece la semilla
datos <- c(-10:-1, 1:10)  # Se crea secuencia de números sin el cero
datos
 [1] -10  -9  -8  -7  -6  -5  -4  -3  -2  -1   1   2   3   4   5   6   7
[18]   8   9  10
B <- sample(x = datos, size = 1)  # Se crean el número números aleatorios
B
[1] -5
# Se crea el condicional
if (B > 0) {
    print(paste("El número generado es positivo e igual a", B))
} else {
    print(paste("El número generado es negativo e igual a", B))
}
[1] "El número generado es negativo e igual a -5"
[1] "La resta es negativa"

Función ifelse

Tome todas las letras del abecedario, y cree una variable \(C\) mediante un condicional, que clasifique las letras entre vocales y consonantes, e imprima el resultado junto con la vocal asociada

# Se crea el condicional
C <- ifelse(letters == "a" | letters == "e" | letters == "i" | letters == "o" | 
    letters == "u", "Vocal", "Consonante")
# Se crea vector con letras y constantes
data.frame(Letras = letters, Clasificación = C)
   Letras Clasificación
1       a         Vocal
2       b    Consonante
3       c    Consonante
4       d    Consonante
5       e         Vocal
6       f    Consonante
7       g    Consonante
8       h    Consonante
9       i         Vocal
10      j    Consonante
11      k    Consonante
12      l    Consonante
13      m    Consonante
14      n    Consonante
15      o         Vocal
16      p    Consonante
17      q    Consonante
18      r    Consonante
19      s    Consonante
20      t    Consonante
21      u         Vocal
22      v    Consonante
23      w    Consonante
24      x    Consonante
25      y    Consonante
26      z    Consonante

Qué es un ciclo?

Un ciclo o bucle, es una acción que tiene por objetivo replicar una o un secuencia de instrucciones un número determinado de veces con cambios menores, a través de uno o varios índices, hasta que se cumpla una condición o un límite máximo de iteraciones establecidas previamente en la construcción del ciclo.

Funciones para ciclos en R

Para el caso de los ciclos, existen tres funciones básicas en R que permiten realizar bucles, es decir, fragmentos de código que se repiten una y otra vez, sin tener que escribir varias veces el mismo fragmento de código. Estas funciones están dadas por for, while y repeat. Adicionalmente, se presenta la función break el cual sirve para detener cualquier ciclo y la función next que sirve para dejar de ejecutar el resto de un ciclo y pasa a ejecutar el siguiente.

La función for() permite ejecutar una secuencia de código un número específico de veces, a partir un índice que se establece mediante una secuencia numérica, vector o lista. El ciclo se ejecutará para cada valor si es una secuencia numérica, recorrerá cada valor si es un vector o para cada elemento sucesivo si es una lista. La estructura de la función for está dada por

for(<índice> in <secuencia>) {
  # Fragmento de código que se ejecuta una y otra vez
}

Por su parte, la función while permite establecer una condición lógica, para repetir un ciclo un sin número de veces, hasta que dicha condición lógica se cumpla. La condición establecida, suele escribirse generalmente mediante el empleo de Operadores lógicos o mediante la comparación entre una variable de control y un valor. La estructura de la función while está dada por

while(<condición>) {
  # Fragmento de código que se ejecuta una y otra vez
}

Finalmente, se tiene la función repeat permite repetir un número indefinido de veces, hasta que se emplee el comando break. Por tanto, para emplear la función repeat será necesario establecer un condicional dentro de la función, para que pueda usarse el comando break. La estructura de la función repeat es de la forma

repeat {
    # Fragmento de código que se ejecuta una y otra vez
}

Función for

Cree una secuencia de número del \(6\) al \(25\), y calcule e imprima de forma iterativa la raíz cuadrada de cada valor de la secuencia, mientras que se cumpla la condición de que la raíz cuadrada es menor a \(4\).

# Se crea la secuencia del 1 al 20
seq <- 6:25
# Creo variable vacía
raíces <- numeric()
# Se crea secuencia
for (i in 1:length(seq)) {
    if (sqrt(seq[i]) >= 4) 
        break
    raíces[i] <- sqrt(seq[i])
}
# Imprimir valor original junto a la raíz
data.frame(Originales = seq[1:length(raíces)], Raíces = raíces)
   Originales   Raíces
1           6 2.449490
2           7 2.645751
3           8 2.828427
4           9 3.000000
5          10 3.162278
6          11 3.316625
7          12 3.464102
8          13 3.605551
9          14 3.741657
10         15 3.872983

Función while

Establezca una semilla igual a \(184\), y haga la selección aleatoria de un número entre el \(1\) y el \(100\). Cree un ciclo, con un contador de iteraciones, en el cual se seleccione un número aleatorio entre \(1\) y \(10\), y se le sume y reemplace el valor inicialmente generado. Repita el ciclo hasta que el número final sea mayor a \(200\), y reporte el número de iteraciones que fueron necesarias para llegar a dicho número.

# Se establece la semilla
set.seed(184)
# Se realiza la selección aleatoria
seleccion <- sample(1:100, size = 1)
# Se crea contador de iteraciones
iteracion <- 0
# Se crea secuencia
while (seleccion <= 200) {
    crecimiento <- sample(1:10, size = 1)
    seleccion <- seleccion + crecimiento
    iteracion <- iteracion + 1
}
print(paste("El número de iteraciones necesarias fue de:", iteracion))
[1] "El número de iteraciones necesarias fue de: 21"

Función repeat

Establezca una semilla igual a \(20\), y genere un número aleatorio de una distribución normal con media \(18\) y varianza \(16\), para emplearla como variable control. Cree un ciclo en cual se generen números aleatorios de una distribución uniforme con límite inferior \(6\) y límite superior \(30\), y guarde los resultados obtenidos en un objeto, hasta que el número generado por la distribución uniforme sea mayor al número generado inicialmente por la distribución normal. Reporte el valor promedio, la desviación estándar obtenida por los números generados al final del ciclo, junto con el número de iteraciones realizadas.

# Se establece la semilla
set.seed(20)
# Se genera el número aleatorio de una normal para control
control <- rnorm(n = 1, mean = 18, sd = sqrt(16))
# Se crea variable vacía para almacenar las variables uniformes
generados <- numeric()
# Se crea una variable de conteo de iteraciones
i <- 0
repeat {
    i <- i + 1
    generados[i] <- runif(n = 1, min = 6, max = 30)
    if (generados[i] > control) 
        break
}
data.frame(media = mean(generados), desv = sd(generados), iteraciones = i)
     media     desv iteraciones
1 20.16827 8.305253           3

Por qué crear función?

Una de las principales ventajas de usar un lenguaje de programación en lugar de un programa que solo use funciones estáticas, es que te da la libertar de crear funciones propias para facilitar o automatizar algunos procesos que se usan recurrentemente, debido a que es posible albergar secuencias completas de código, dentro de una función para usarla posteriormente, sin tener que volver a realizar la misma programación en el mismo código. Usualmente se crean funciones cuando hay que realizar presentaciones, investigaciones o cuando se deba compartir el código con el público.

Crear funciones en R

Para definir funciones nuevas en R es necesario emplear la función function, la cual posee una estructura de la forma

<nombre> <- function(<argumento1>, <argumento2>, <argumento3>, ...) {
  # Fragmento de código que se desea incorporar en la función
}

Una aspecto importante de las funciones es que éstas pueden dividirse en $3$ tipos de elementos diferentes. El primero, está asociado a los argumentos que se le dan a la función, éstos pueden ser múltiples y deben separarse por coma unos de otros. Adicionalmente, existe un argumento en particular, dado por tres puntos consecutivos “$\ldots$”, el cual permite pasar un número variable de argumentos de una función a otra.

El segundo, está asociado al cuerpo que se le da a la función, es decir, las operaciones que se desean ejecutar cuando se emplee la función, en donde, estas operaciones suelen emplear los argumentos anteriormente mencionados.

El tercer y último elemento, está asociado a los resultados que se tendrán al emplear la función, es decir, el o los valores que entrega la función una vez ésta realiza las operaciones que se han ejecutado en el cuerpo. Usualmente, para entregar los resultados de la función, se suele emplear la función return, en la cual se indicarán qué valores son los que se desean devolver.

Función function

Cree una función que permita calcular la probabilidad de obtener más de \(3\) caras en el lanzamiento de \(10\) monedas, y compare el resultado obtenido con el de una distribución binomial.

# Se crea función la función
mipbinom <- function(x, n, p, izquierda = T) {
    prob <- numeric()
    if (izquierda == T) {
        # P(X<=x)
        for (k in 0:x) {
            prob[k + 1] <- choose(n = n, k = k) * p^k * (1 - p)^(n - k)
        }
    } else {
        for (k in (x + 1):n) {
            # P(X>x)
            prob[k - x] <- choose(n = n, k = k) * p^k * (1 - p)^(n - k)
        }
    }
    return(Prob = sum(prob))
}
# Se emplea función creada
mipbinom(x = 3, n = 10, p = 0.5, izquierda = F)
[1] 0.828125
# Se emplea función binomial
pbinom(q = 3, size = 10, prob = 0.5, lower.tail = F)
[1] 0.828125