Curso básico de R:
Funciones

Francesc Carmona

15 de octubre de 2022




El objetivo principal de este curso es proporcionar los elementos básicos para empezar a trabajar con el lenguaje de programación R en el ámbito de la Estadística.

Este curso está basado muy especialmente en el documento Introducción al uso y programación del sistema estadístico R
de Ramón Díaz-Uriarte de la Unidad de Bioinformática del CNIO.

Funciones

Definición

nombre <- function(arg1, arg2, ...){expresión}
suma <- function(a1,d,n){
               an <- a1+(n-1)*d
               ((a1+an)*n)/2
               }

Plantilla básica

La plantilla básica de una función es

function_name <- function(function_arguments) { 
  function_body
  function_return_value
}

Cada uno de ellos es importante.

El nombre

El nombre de la función puede ser casi cualquier cosa, incluso funciones o variables definidas previamente, así que tenga cuidado. Una vez que haya dado el nombre, puede usarlo como cualquier otra función, con paréntesis. Por ejemplo, para definir una función de desviación estándar usando la función var(), podemos hacer

std <- function(x) sqrt(var(x))

Se puede llamar sin paréntesis y así se obtiene la definición misma

std
## function(x) sqrt(var(x))

Argumentos

hello.world <- function() print("hello world") 
hello.world()
## [1] "hello world"
hello.someone <- function(name) print(paste("hello", name)) 
hello.someone("fred")
## [1] "hello fred"

Si la función hello.someone() anterior se utiliza sin valor para el argumento, da error.

hello.someone()

Para corregir esta situación podemos dar un valor por defecto.

hello.someone <- function(name="world") print(paste("hello ",name))
hello.someone()
## [1] "hello  world"

La expresión name="world" no es una asignación.

Argumentos (2)

una.f <- function(a, b, c = 4, d = FALSE){x1 <- a*z ...}
una.f(4, 5)
una.f(b = 5, a = 4)
una.f(c = 25, 4, 5) # error
f3 <- function(x, y, label = "la x", ...){
                    plot(x, y, xlab = label, ...)
                    }
  
f3(1:5, 1:5)
f3(1:5, 1:5, col = "red")
f <- function(x, y){cos(y)/(x^2-3)}
z <- outer(x, y, f)

Cuerpo de la función y valor de retorno

Scope

cubo <- function(n){
          sq <- function() n*n # aquí n no es un argumento
          n*sq()
          }

Control de ejecución

if(cond) expr
if(cond) cons.expr  else  alt.expr
for(var in seq) expr
while(cond) expr
repeat expr
break
next
f4 <- function(x){
         if(x > 5) print("x > 5")
         else {
           y <- runif(1)
           print(paste("y is ", y))
         }
      }

Control de ejecución (2)

odd.even <- function(x){
              ifelse(x %% 2 == 1, "Odd", "Even")
            }
mtf <- matrix(c(TRUE, FALSE, TRUE, TRUE), nrow = 2)
ifelse(mtf, 0, 1)
##      [,1] [,2]
## [1,]    0    0
## [2,]    1    0
for(i in 1:10) cat("el valor de i es", i, "\n")
## el valor de i es 1 
## el valor de i es 2 
## el valor de i es 3 
## el valor de i es 4 
## el valor de i es 5 
## el valor de i es 6 
## el valor de i es 7 
## el valor de i es 8 
## el valor de i es 9 
## el valor de i es 10
continue.loop <- TRUE
x <- 0
while(continue.loop){
        x <- x + 1
        print(x)
        if( x > 10) continue.loop <- FALSE
      }
## [1] 1
## [1] 2
## [1] 3
## [1] 4
## [1] 5
## [1] 6
## [1] 7
## [1] 8
## [1] 9
## [1] 10
## [1] 11

Cuando algo va mal

debug(my.buggy.function)
...
undebug(my.buggy.function)

Ejemplo

my.f2 <- function(x, y){
          z <- rnorm(10) + y2 <- z * y + y3 <- z * y * x + return(y3 + 25)
          }
my.f2(runif(3), 1:4)
debug(my.f2)
my.f2(runif(3), 1:4)
undebug(my.f2)
# insertar un browser() y correr de nuevo

Ejecución no interactiva

source("mi.fichero.con.codigo.R")
$ Rcmd BATCH mi.fichero.con.codigo.R

Se pueden crear paquetes, con nuestras funciones, que se comporten igual que los demás paquetes. Ver Writing R extensions.

R puede llamar código compilado en C/C++ y FORTRAN. Ver .C, .Call, .Fortran.

No hemos mencionado el computing on the language (ej., do.call, eval, etc.).