septiembre de 2016

Funciones

  • Las funciones se crean usando la directiva function() y son almacenadas como objetos R exactamente igual que cualquier otro. En particular, son objetos R de la clase "function".
f <- function(<argumentos>) {
  # hacer algo interesante
}
  • Las funciones en R son "objetos de primera clase", lo que significa que pueden considerarse como cualquier otro objeto R.
    • Las funciones pueden ser pasadas como argumentos a otras funciones.
    • Las funciones pueden ser anidadas, así que puede definirse una función dentro de otra función.
  • El valor devuelto de una función es la última expresión en el cuerpo de la función que se evaluó.
  • Los nombres de la función puede ser casi cualquier cosa. Sin embargo, debe evitarse el uso de nombres de funciones existentes.
  • Reglas de alcance. Las variables creadas dentro de una función existen solamente en el tiempo de vida de la llamada a la función. Por lo que no son accesibles fuera de la función. Para forzar que variables en funciones sean vistas globalmente, puede usarse el operador de asignación global <--.

Ejemplos de funciones

es.par <- function(un.numero){
    resto <- un.numero %% 2
    if (resto==0)
        return(TRUE)
    return(FALSE) 
}
es.par(10)
## [1] TRUE
es.par(9)
## [1] FALSE

Ejemplos de funciones (continua)

es.divisible.por <- function(numero.grande, numero.pequeno){
 if (numero.grande %% numero.pequeno != 0)
   return(FALSE)
 return(TRUE)
}
es.divisible.por(10, 2)
## [1] TRUE
es.divisible.por(10, 3)
## [1] FALSE
es.divisible.por(9, 3)
## [1] TRUE

Ejemplos de funciones (continua)

es.par2 <- function(num){ 
  es.divisible.por(num, 2) 
}
es.par2(10)
## [1] TRUE
es.par2(9)
## [1] FALSE

Ejemplos de funciones (continua)

myfct <- function(x1, x2=5) { 
    z1 <- x1/x1
    z2 <- x2*x2
    myvec <- c(z1, z2) 
    return(myvec)
} 
myfct(x1=2, x2=5) # aplica la función a los valores 2 y 5
## [1]  1 25
myfct(2, 5) # los nombres de argumentos no serán necesarios, 
## [1]  1 25
            # pero el orden especificado es importante
myfct(x1=2) # igual que antes, pero el valor por defecto '5' se usa en este caso
## [1]  1 25

Ejemplos de funciones (continua)

myfct # imprime la definición de la función
## function(x1, x2=5) { 
##     z1 <- x1/x1
##     z2 <- x2*x2
##     myvec <- c(z1, z2) 
##     return(myvec)
## }

Función con argumentos opcionales

myfct2 <- function(x1=5, opt_arg) {
        if(missing(opt_arg)) { # 'missing()' se usa para probar si se especificó un valor como argumento
            z1 <- 1:10 
        } else {
            z1 <- opt_arg 
        }   
        cat("mi función devuelve:", "\n")
        return(z1/x1)
}  
myfct2(x1=5) # realiza cálculos sobre vector por defecto (z1) definido en función
## mi función devuelve:
##  [1] 0.2 0.4 0.6 0.8 1.0 1.2 1.4 1.6 1.8 2.0
myfct2(x1=5, opt_arg=30:20) # se usa un vector personalizado en lugar del argumento opcional (opt_arg)
## mi función devuelve:
##  [1] 6.0 5.8 5.6 5.4 5.2 5.0 4.8 4.6 4.4 4.2 4.0

Encontrando argumentos

  • Los argumentos de las funciones R pueden encontrarse por posición o por nombre. Por ejemplo, las siguientes llamadas a la función sd son todas equivalentes.
misdatos = rnorm(100)
sd(misdatos)
sd(x = misdatos)
sd(x = misdatos, na.rm=FALSE)
sd(na.rm = FALSE, x = misdatos)
sd(na.rm = FALSE, misdatos)
  • Aunque es legal, no se recomienda mezclar el orden de los argumentos mucho, ya que puede llevar a confusión.

Definir una función

f = function(a, b=1, c=2, d=NULL) {
  
}

Además para no especificar un valor por defecto, podemos también definir un valor de argumento igual a NULL.

Evaluación perezosa (lazy)

  • Los argumentos para las funciones son evaluados de forma perozosa, ya que se evalúan solamente cuando se necesita.
f = function(a, b) {
  a^2
}
f(2)
  • Esta función realmente nunca usa el argumento b, al llamar f(2) no producirá ningún error ya que el 2 encuentra el argumento a por posición.

  • Otro ejemplo

f = function(a, b) {
  print(a)
  print(b)
}
#> f(45)
#[1] 45
#Error in print(b) : el argumento "b" está ausente, sin valor por omisión
  • Observa que "45" se imprime primero antes de que se produzca el lanzamiento del error. Esto es porque "b" no tiene que ser evaluado hasta después de "print(a)". Una vez que la función intenta evaluar "print(b)" lanza el error.

El argumento "…"

  • El argumento "…" indica un número variable de argumentos que son pasados realmente a otras funciones.
    • "…" se usa habitualmente cuando extendemos otra función y no queremos copiar la lista de argumentos completa de la función original.
miplot = function(x, y, tipo=T, ...) {
  plot(x,y,type=tipo,...)
}

El argumento "…"

  • Las funciones genéricas usan "…" para pasar argumentos extras a los métodos.
mean
## function (x, ...) 
## UseMethod("mean")
## <bytecode: 0x7ff3c5539db8>
## <environment: namespace:base>
  • El argumento "…" es también necesario cuando el número de argumentos pasado a la función no se puede conocer por adelantado.
args(paste)
## function (..., sep = " ", collapse = NULL) 
## NULL

Argumentos que llegan después de "…"

  • Un problema con "…" es que cualquier argumento que aparezca después de "…" sobre la lista de argumentos debe tener el nombre exacto y no parcialmente.
args(paste)
## function (..., sep = " ", collapse = NULL) 
## NULL
paste("a","b",sep=":")
## [1] "a:b"
paste("a","b",se=":")
## [1] "a b :"

Utilidades de control para funciones: return, warning y stop

  • return: el flujo de evaluación de una función puede terminarse en cualquier parte con la función return(). Generalmente se usa con evaluaciones de condicionales.
  • stop(): para detener la acción de una función y mostrar un mensaje de error, puede usarse la función stop.
  • warning(): imprime un mensaje de aviso en situaciones inesperadas sin abortar el flujo de evaluación de la función.

Utilidades de control para funciones: return, warning y stop

myfct <- function(x1) {
        if (x1>=0) print(x1) else stop("Esta función no finaliza, ya que x1 < 0")
        warning("Valor necesita ser  > 0")
}
myfct(x1=2)
# [1] 2
# Warning message:
# In myfct(x1 = 2) : Valor necesita ser  > 0
myfct(x1=-2)
# Error in myfct(x1 = -2) : Esta función no finaliza, ya que x1 < 0

Utilidades de debugging (depuración de código)

Hay varias utilidades en R para hacer depuración (debugging) de código (y también en RStudio). Las más conocidas son: browser() y debug().