# Definición de la función
<- function() {
saludo print("¡Hola!")
}class(saludo)
[1] "function"
# Llamada a la función
saludo()
[1] "¡Hola!"
Una función es un bloque de código que tiene asociado un nombre, de manera que cada vez que se quiera ejecutar el bloque de código basta con invocar el nombre de la función. Las funciones permite dividir el código en unidades lógicas que resultan más fáciles de manejar y mantener.
En R las funciones son objetos en sí mimas y pueden usarse como cualquier otro dato. El tipo de dato de las funciones es function
.
Para definir una función se utiliza la siguiente estructura de código:
nombre.funcion
<- function (
parámetros
) {
<código>
}
El código que va entre llaves se conoce como cuerpo de la función.
Para llamar a la función y que se ejecute el código de su cuerpo hay que utilizar el nombre de la función y a continuación los valores pasados a sus parámetros entre paréntesis.
Ejemplo 5.1
# Definición de la función
<- function() {
saludo print("¡Hola!")
}class(saludo)
[1] "function"
# Llamada a la función
saludo()
[1] "¡Hola!"
Una función puede recibir valores cuando se invoca a través de unas variables conocidas como parámetros que se definen entre paréntesis en la declaración de la función. En el cuerpo de la función se pueden usar estos parámetros como si fuesen variables.
Los valores que se pasan a la función en una llamada o invocación concreta de ella se conocen como argumentos y se asocian a los parámetros de la declaración de la función.
Ejemplo 5.2
# Función con un parámetro
<- function(nombre) {
saludo print(paste("¡Hola ", nombre, "!", sep = ""))
}# Llamada a la función con un argumento
saludo("Alf")
[1] "¡Hola Alf!"
En este ejemplo la función saludo
tiene un parámetro nombre
. En la llamada a la función se pasa la cadena Alf
como argumento que se asocia al parámetro nombre
en el cuerpo de la función.
Los argumentos de una función pueden pasarse de dos formas:
parametro = argumento
. En este caso el orden de los argumentos no importa.Ejemplo 5.3
# Función con un argumento por defecto
<- function(base, altura) {
area.triangulo * altura / 2
base
}# Cálculo del área de un triángulo de base 4 y altura 3
# Paso de argumentos por posición.
area.triangulo(4, 3)
[1] 6
# Paso de argumentos por nombre
area.triangulo(altura = 3, base = 4)
[1] 6
En la definición de una función se puede asignar a cada parámetro un argumento por defecto, de manera que si se invoca la función sin proporcionar ningún argumento para ese parámetro, se utiliza el argumento por defecto.
Ejemplo 5.4
<- function(nombre, lenguaje = "R") {
saludo print(paste("¡Hola ", nombre, "! ¡Bienvenido a ", lenguaje, "!", sep = ""))
}# Llamada a la función con un argumento
saludo("Alf")
[1] "¡Hola Alf! ¡Bienvenido a R!"
Una función puede devolver un objeto de cualquier tipo tras su invocación. Para ello se utiliza la función return()
, indicando entre paréntesis el valor que devuelve la función. El retorno suele realizarse al final del cuerpo de la función, porque con él finaliza la ejecución de la función y se devuelve el control de la ejecución al punto desde donde se llamó a la función, de manera que cualquier instrucción de cuerpo que vaya después no se ejecutará. Si no se indica ningún objeto, la función devolverá el valor de la última expresión calculada en el cuerpo de la función.
Ejemplo 5.5
# Función que devuelve el area de un triángulo
<- function(base, altura) {
area.triangulo return(base * altura / 2)
}area.triangulo(4, 3)
[1] 6
# Función que devuelve el valor absoluto de un número
<- function(x) {
valor.absoluto if (x < 0)
return(x * -1)
else
return(x)
}valor.absoluto(-1)
[1] 1
valor.absoluto(2)
[1] 2
Para devolver más de un valor se pueden utilizar estructuras de datos como vectores, listas, matrices o data frames.
Ejemplo 5.6
<- function(radio) {
circulo return(list(perimetro = 2 * pi * radio, area = pi * radio ^ 2))
}circulo(5)
$perimetro
[1] 31.41593
$area
[1] 78.53982
circulo(5)$perimetro
[1] 31.41593
circulo(5)$area
[1] 78.53982
El entorno de un programa en R es el conjunto de todos los objetos (funciones, variables, etc.) creados durante la ejecución del programa. Cuando se ejecuta el interprete de R siempre se crea un primer entorno R_GlobalEnv
conocido como entorno global. Es posible referirse a él en cualquier momento con la constante .GlobalEnv
.
Para ver el entorno activo en cada momento de la ejecución y el contenido del mismo se utiliza la siguiente función:
environment()
: Devuelve el nombre del entorno actual.ls()
: Devuelve un vector con los nombres de las objetos (variables, funciones, etc.) que contiene el entorno global.Ejemplo 5.7
<- 4
x <- 3
y <- function(base, altura) {
area.triangulo * altura / 2
base
}environment()
<environment: R_GlobalEnv>
ls()
[1] "area.triangulo" "x" "y"
Como se puede observar en el ejemplo anterior, los parámetros de la función base
y altura
no aparecen en el entorno global. En R, cuando se ejecuta una función se crea un nuevo entorno hijo dentro del entorno al que pertenece la función. Durante la ejecución de la función este pasa a ser el entorno activo y cuando termina la ejecución de la función deja de serlo y vuelve a activarse el entorno padre desde donde se llamó a la función.
Ejemplo 5.8
<- 4
x <- 3
y <- function(base, altura) {
area.triangulo print("Entorno de la función area.triangulo")
print(environment())
print(ls())
return(base * altura / 2)
}print("Entorno fuera de la función")
[1] "Entorno fuera de la función"
environment()
<environment: R_GlobalEnv>
ls()
[1] "area.triangulo" "x" "y"
area.triangulo(x, y)
[1] "Entorno de la función area.triangulo"
<environment: 0x55bb10871900>
[1] "altura" "base"
[1] 6
Los parámetros y los objetos (funciones, variables, etc.) definidos dentro de una función son de ámbito local, mientras que los objetos definidos fuera de ella en alguno de los entornos ancestros son de ámbito global.
Tanto los parámetros como las variables del ámbito local de una función sólo están accesibles durante la ejecución de la función, es decir, cuando termina la ejecución de la función estas variables desaparecen y no son accesibles desde fuera de la función.
Cuando una función declara un objeto (función, variable, etc.) que ya existe en alguno de los entornos ancestros con ámbito global, durante la ejecución de la función el objeto global queda eclipsado por el local y no es accesible hasta que finaliza la ejecución de la función.
Ejemplo 5.9
= "Python"
lenguaje <- function(lenguaje) {
saludo print(paste("Bienvenido a", lenguaje))
}saludo("R")
[1] "Bienvenido a R"
Obsérvese cómo al ejecutar la función anterior, la variable lenguaje
queda inaccesible al tener la función un parámetro con el mismo nombre.
Las variables globales están accesibles siempre que no sean eclipsadas por otras con el mismo nombre de ámbito local. Si embargo, cuando se intenta asignar un valor a una variable global en el ámbito local, se crea una nueva variable local. Para asignar valores a variables globales en el ámbito local se tiene que utilizar el operador de superasignación <<-
. Cuando se utiliza este operador para asignar un valor a una variable, R busca la variable entorno padre, y si no existe continua con la búsqueda en los entornos ancestros hasta llegar a entorno global. Si la búsqueda tiene éxito, asigna el nuevo valor a la variable global, mientras que si no tiene éxito se crea una nueva variable de ámbito local y se le asigna el valor.
Ejemplo 5.10
<- function() {
saludo <<- "R"
lenguaje return(paste("Bienvenido a", lenguaje))
} lenguaje
[1] "Python"
Los tres componentes de una función son:
Para acceder a estos componentes se pueden utilizar las siguientes funciones:
body(f)
: Devuelve el cuerpo de la función f
.formals(f)
: Devuelve la lista de parámetros de la función f
.environment(f)
: Devuelve el entorno de la función f
.Ejemplo 5.11
# Definición de la función
<- function(base, altura) {
area.triangulo * altura / 2
base
}body(area.triangulo)
{
base * altura/2
}
formals(area.triangulo)
$base
$altura
environment(saludo)
<environment: R_GlobalEnv>
Una función recursiva es una función que en su cuerpo contiene una llama a sí misma.
La recursión es una práctica común en la mayoría de los lenguajes de programación ya que permite resolver las tareas recursivas de manera más natural.
Para garantizar el final de una función recursiva, las sucesivas llamadas tienen que reducir el grado de complejidad del problema, hasta que este pueda resolverse directamente sin necesidad de volver a llamar a la función. De lo contrario la recursión no tendría fin y nunca terminaría la ejecución de la función.
Ejemplo 5.12
<- function(n) {
factorial if (n <= 1) return(n)
else return(n * factorial(n - 1))
}factorial(4)
[1] 24
Para facilitar la reutilización código y datos R permite la creación de paquetes que pueden importarse desde otros programas. Un paquete es una colección de código, funciones y datos que se almacenan en un fichero dentro de un directorio llamado library
en el entorno de R. Para ver la ubicación de este directorio dentro del sistema de archivos local se puede utilizar la función .libPaths()
.
Ejemplo 5.13
.libPaths()
[1] "/home/alf/R/x86_64-pc-linux-gnu-library/4.2"
[2] "/usr/lib/R/library"
Durante la instalación de R también se instalan varios paquetes básicos que están disponibles en cualquier sesión de trabajo con R. Pero añadir nuevas funciones o procedimientos es necesario instalar el paquete que los contiene y después cargarlo en la sesión de trabajo.
Para ver los paquetes instalados en un ordenador se utiliza la función library()
.
La mayor parte de los paquetes para R están disponibles en el repositorio oficial CRAN (Comprehensive R Archive Network), aunque cualquier persona puede desarrollar un paquete y ponerlo a disposición de la comunidad en cualquier otro repositorio.
Existen distintas formas de instalar un paquete en R:
Para instalar un paquete desde el repositorio oficial CRAN se utiliza la siguiente función:
install.packages(x)
: Obtiene el paquete con el nombre x
desde un servidor con el repositorio CRAN y lo instala localmente en el directorio library
del entorno de R. Se puede instalar más de un paquete a la vez pasando un vector con los nombres de los paquetes.Ejemplo 5.14
install.packages("remotes")
El paquete remotes
incorpora funciones para instalar paquetes alojados en otros repositorios habituales para el desarrollo de software como GitHub, GitLab, etc.
Ejemplo 5.15
install.packages("remotes")
::install_github("rkward-community/rk.Teaching") remotes
Bioconductor es un repositorio de paquetes especializados en Bioinformática.
Bioconductor utiliza sus propio gestor de paquetes BiocManager
, pero la instalación de paquetes es igualmente sencilla.
Ejemplo 5.16
install.packages("BiocManager")
::install("edgeR") BiocManager
Finalmente es posible instalar un paquete manualmente a partir de su código fuente. Para ello hay previamente hay que descargar el código fuente del paquete en un fichero comprimido en formato zip y después utilizar la siguiente función:
install.packages(x, repos = NULL, type = "source")
: Instala el paquete ubicado en la ruta x
del sistema de archivos local en la librería library
.Una vez instalado un paquete ya está disponible para cargarlo en cualquier sesión de trabajo de R y no es necesario volver a instalarlo.
Una vez instalado un paquete, para poder ejecutar su contenido es necesario cargarlo en el entorno de trabajo de R. Para ello se utiliza la siguiente función:
library(x)
: Ejecuta el código del paquete x
en la sesión de trabajo activa.Ejemplo 5.17
library("remotes")
A continuación se presenta una lista ordenada alfabéticamente (no por importancia) de los paquetes más populares para el análisis de datos:
caret
es un paquete para la creación de modelos de clasificación y regresión mediante aprendizaje automático.data.table
es un paquete para la manipulación de grandes conjuntos de datos (de hasta 100GB) de manera rápida y eficiente.devtools
es un paquete con herramientas para el desarrollo de paquetes en R.knitr
es un paquete que proporciona un motor para la generación de informes dinámicos que permite la integración de código en R con los lenguajes de procesamiento de textos LaTeX, HTML, Markdown, AsciiDoc o reStructuredText.mlr3
es un paquete que proporciona funciones para las principales técnicas de aprendizaje automático.plotly
es un paquete para la creación de gráficos interactivos.rmarkdown
es un paquete que facilita el uso del paquete knitr
para la elaboración de documentos en múltiples formatos (HTML, pdf, Word y otros) permitiendo la integración de código R en el lenguaje Markdown.shiny
es un paquete para la construcción de aplicaciones web interactivas.tidymodels
es una colección de paquetes para la construcción y evalucación de modelos con técnicas de aprendizaje automático.tidyverse
es una colección de paquetes para la Ciencia de Datos que incluye paquetes para la carga, limpieza, manipulación y representación gráfica de datos.