Hasta ahora hemos explorado las expresiones habituales de cualquier lenguaje de programación a la hora de establecer procesos automáticos. Sin embargo, vemos que a lo largo de todos estos ejemplos hay una serie de objetos o de elementos que son fijos, o bien son elementos designados de antemano. Muchas veces, si todo nuestro código lo metemos en una función propia, podremos ajustarla y hacerla más flexible de acuerdo a nuestras necesidades. Esto significa que de un solo golpe le pediremos a R que ejecute todo lo que pretendíamos hacer.
Supongamos entonces que en nuestro trabajo de análisis se nos pide de manera repetida que saquemos gráficos de los datos de concentración de CO2 medido en el observatorio de Mauna Loa para un año dado, y que demos la media de ese año. Las operaciones a realizar son:
Por ejemplo, me piden que saque los datos del año 2000.
library(tidyverse)
## Warning: package 'tidyverse' was built under R version 3.5.3
## -- Attaching packages ----------------------------------------------------------------------------------------------------------- tidyverse 1.3.0 --
## v ggplot2 3.3.0 v purrr 0.3.4
## v tibble 3.0.1 v dplyr 0.8.5
## v tidyr 1.0.2 v stringr 1.4.0
## v readr 1.3.1 v forcats 0.5.0
## Warning: package 'ggplot2' was built under R version 3.5.3
## Warning: package 'tibble' was built under R version 3.5.3
## Warning: package 'tidyr' was built under R version 3.5.3
## Warning: package 'readr' was built under R version 3.5.3
## Warning: package 'purrr' was built under R version 3.5.3
## Warning: package 'dplyr' was built under R version 3.5.3
## Warning: package 'stringr' was built under R version 3.5.3
## Warning: package 'forcats' was built under R version 3.5.3
## -- Conflicts -------------------------------------------------------------------------------------------------------------- tidyverse_conflicts() --
## x dplyr::filter() masks stats::filter()
## x dplyr::lag() masks stats::lag()
mauna<-read_delim("maunaloa.csv",delim=",")
## Parsed with column specification:
## cols(
## year = col_double(),
## month = col_double(),
## day = col_double(),
## decimalday = col_double(),
## ppm = col_double(),
## date = col_date(format = "")
## )
seleccion<-subset(mauna,year==2000)
ggplot(seleccion,aes(x=date,y=ppm))+geom_line()
mean(na.omit(seleccion$ppm))
## [1] 369.5775
Si esto me lo piden de manera recurrente puedo hacer mi trabajo más eficiente si lo hago en una función. La manera más sencilla en la que puedo hacer esto es seleccionar todas las líneas que quiero que mi función personal incluya. Ir a Code->extract function
y darle un nombre a la función en la ventana emergente que me pregunta (“mauna_analysis” en mi caso). Este es el resultado:
mauna_analysis <- function(tidyverse, year, date, ppm) {
library(tidyverse)
mauna<-read_delim("maunaloa.csv",delim=",")
seleccion<-subset(mauna,year==2000)
ggplot(seleccion,aes(x=date,y=ppm))+geom_line()
mean(na.omit(seleccion$ppm))
}
De manera automática ha identificado cuatro argumentos que piensa que le tengo que dar a la función. Esto es así porque Rstudio busca dentro de la función todos los objetos que hay introducidos como argumentos de las instrucciones que contiene nuestra nueva función. Y pone como argumentos entonces aquellos objetos que no se generan dentro de la función, y que tienen que ser generados o bien fuera, o bien especificándolos como argumentos cuando llame a mi función nueva. Si no los genero en ese momento o no han sido creados antes de la función, no van a existir. En realidad estamos en el segundo caso para los argumentos tidyverse, date y ppm. El primero es el nombre de un paquete y no necesito que sea un argumento. Los otros dos nombres de columnas que voy a obtener al leer mi archivo de datos. Solo year es el que necesito para personalizar mi función, puesto que ese es su propósito: decirle un año concreto y que me saque los dos datos que le he pedido de ese año. Y sí lo tendré que especificar como argumento.
Además tengo que camiar la tercera línea de la función, para que me seleccione no los datos del 2000 sino los datos del año que seleccione en mi argumento year:
mauna_analysis <- function(year) {
library(tidyverse)
mauna<-read_delim("maunaloa.csv",delim=",")
seleccion<-subset(mauna,year==year)
ggplot(seleccion,aes(x=date,y=ppm))+geom_line()
mean(na.omit(seleccion$ppm))
}
mauna_analysis(1997)
## Parsed with column specification:
## cols(
## year = col_double(),
## month = col_double(),
## day = col_double(),
## decimalday = col_double(),
## ppm = col_double(),
## date = col_date(format = "")
## )
## [1] 367.0459
Sin embargo yo le había pedido que me sacara un gráfico con ggplot: ¿Dónde está? Para poder utilizar ggplot en una función o en un bucle es necesario guardarlo como un objeto y luego sacarlo con print()
.
Además, y esto es muy importante, para poder guardar mis resultados numéricos o de cualquier otro tipo que sean resultados de mis cálculos en una función, tengo que poner, como línea final de mi función, la instrucción return()
con el dato/objeto/dataframe o lo que sea que sea el producto de mi función. Si no, ese dato no se producirá como resultado de la función. Como mucho, puede salir por pantalla como en el caso anterior.
mauna_analysis <- function(year) {
library(tidyverse)
mauna<-read_delim("maunaloa.csv",delim=",")
seleccion<-subset(mauna,year==year)
grafico<-ggplot(seleccion,aes(x=date,y=ppm))+geom_line()
print(grafico)
media<-mean(na.omit(seleccion$ppm))
return(media)
}
mauna_analysis(year=1985)
## Parsed with column specification:
## cols(
## year = col_double(),
## month = col_double(),
## day = col_double(),
## decimalday = col_double(),
## ppm = col_double(),
## date = col_date(format = "")
## )
Es posible que hayáis reparado en que muchas funciones tienen muchos argumentos, pero normalmente especificamos uno, dos, o a veces ninguno.El resto los dejamos por defecto, y si no lo especificamos, R tomará ese argumento por defecto. Podemos hacer lo mismo especificándolo en la primera línea de la función. En este caso le voy a decir que el año por defecto sea 1990, el año de referencia del Grupo Intergubernamenteal para el cambio Climático (el IPCC):
mauna_analysis <- function(year=1990) {
library(tidyverse)
mauna<-read_delim("maunaloa.csv",delim=",")
seleccion<-subset(mauna,year==year)
grafico<-ggplot(seleccion,aes(x=date,y=ppm))+geom_line()
print(grafico)
media<-mean(na.omit(seleccion$ppm))
return(media)
}
mauna_analysis()
## Parsed with column specification:
## cols(
## year = col_double(),
## month = col_double(),
## day = col_double(),
## decimalday = col_double(),
## ppm = col_double(),
## date = col_date(format = "")
## )
Si tenemos qu sacar los gráficos de varios años, será más sencillo de esta manera. Lo podemos combinar con un bucle:
años_a_analizar<-c(1985,1991,2007,2008)
for(años in años_a_analizar){
mauna_analysis(años)
}