Los fundamentos de programación son esenciales a la hora de ahorrar un tiempo muy valioso en nuestros análisis. Como ya avisábamos en un principio, si nuestro código es muy repetitivo la programación y la automatización que hemos visto es un elemento vital para no extenuarse con esta herramienta.

Sin embargo, lo visto hasta ahora no es la única manera. Como avisábamos, la programación funcional, la que utiliza funciones que sustituyen a los bucles puede ser sumamente efectiva por dos razones:

La clave de la programación funcional es la familia de funciones apply. Se trata de un conjunto de funciones básicas que ejecutarán una función determinada sobre una secuencia (como en for), una matriz, una lista, etc. con los parámetros que le digamos. La función principal es apply, pero vamos a ver también sapply y lapply. Otras como tapply, mapply y vapply.

La estructura de funcionamiento es similar pero varía ligeramente porque las funciones no se usan para los mismos tipos de datos. COmo función principal, apply se usa para matrices o dataframes, y lapply/sapply para vectores así que hay ciertas diferencias. El patrón en cualquier caso es: funcion_apply(vector_o_matriz,funcion_a_aplicar_iterativamente,parametros_de_la_funcion_a_aplicar).

La función apply() tiene tres parámetors como veíamos arriba: el objeto sobre el que queremos aplicar una función (para apply, matriz o dataframe), el parámetro MARGIN, y el parámetro FUN. FUN especifica, sin comillas, el nombre de la función que queremos aplicar. Y MARGIN especifica si queremos aplicarlo por filas (=1) o columnas (=2).

apply(mimatriz,MARGIN=2,FUN)

Vamos a verlo con una matriz con números de 1 a 100 creada con la función matrix(), con 20 filas y 5 columnas:

matriz<-matrix(1:100,nrow=20,ncol=5)
matriz
##       [,1] [,2] [,3] [,4] [,5]
##  [1,]    1   21   41   61   81
##  [2,]    2   22   42   62   82
##  [3,]    3   23   43   63   83
##  [4,]    4   24   44   64   84
##  [5,]    5   25   45   65   85
##  [6,]    6   26   46   66   86
##  [7,]    7   27   47   67   87
##  [8,]    8   28   48   68   88
##  [9,]    9   29   49   69   89
## [10,]   10   30   50   70   90
## [11,]   11   31   51   71   91
## [12,]   12   32   52   72   92
## [13,]   13   33   53   73   93
## [14,]   14   34   54   74   94
## [15,]   15   35   55   75   95
## [16,]   16   36   56   76   96
## [17,]   17   37   57   77   97
## [18,]   18   38   58   78   98
## [19,]   19   39   59   79   99
## [20,]   20   40   60   80  100

Ahora le vamos a aplicar apply por columnas con la raíz cuadrada:

apply(matriz,MARGIN=1,FUN=sqrt)
##          [,1]     [,2]     [,3]     [,4]     [,5]     [,6]     [,7]     [,8]
## [1,] 1.000000 1.414214 1.732051 2.000000 2.236068 2.449490 2.645751 2.828427
## [2,] 4.582576 4.690416 4.795832 4.898979 5.000000 5.099020 5.196152 5.291503
## [3,] 6.403124 6.480741 6.557439 6.633250 6.708204 6.782330 6.855655 6.928203
## [4,] 7.810250 7.874008 7.937254 8.000000 8.062258 8.124038 8.185353 8.246211
## [5,] 9.000000 9.055385 9.110434 9.165151 9.219544 9.273618 9.327379 9.380832
##          [,9]    [,10]    [,11]    [,12]    [,13]    [,14]    [,15]    [,16]
## [1,] 3.000000 3.162278 3.316625 3.464102 3.605551 3.741657 3.872983 4.000000
## [2,] 5.385165 5.477226 5.567764 5.656854 5.744563 5.830952 5.916080 6.000000
## [3,] 7.000000 7.071068 7.141428 7.211103 7.280110 7.348469 7.416198 7.483315
## [4,] 8.306624 8.366600 8.426150 8.485281 8.544004 8.602325 8.660254 8.717798
## [5,] 9.433981 9.486833 9.539392 9.591663 9.643651 9.695360 9.746794 9.797959
##         [,17]    [,18]    [,19]     [,20]
## [1,] 4.123106 4.242641 4.358899  4.472136
## [2,] 6.082763 6.164414 6.244998  6.324555
## [3,] 7.549834 7.615773 7.681146  7.745967
## [4,] 8.774964 8.831761 8.888194  8.944272
## [5,] 9.848858 9.899495 9.949874 10.000000

Las funciones sapply() y lapply() funcionan con vectores especificando los tres argumentos de arriba (el vector de donde tomar los elementos, la función a aplicarles, y los argumentos extra. La función que especifico cogerá como su primer argumento cada uno de los elementos del vector, aplicándoles la función y los argumentos extra, uno a uno.

La diferencia entre ellas cómo almacenan y muestran los resultados

El ejemplo que utilizaremos es un truco para cargar muchos paquetes a la vez sin recurrir individualmente a library() y cambiándolo por la función require().

Defino una vector con los nombres (por tanto entre comillas de los paquetes que quiero cargar. Añadiré como argumento extra, el argumento de la función require(), character.only=TRUE.

paquetes<-c("ggplot","raster","sp", "sudoku")
lapply(paquetes,require,character.only=TRUE)
## Loading required package: ggplot
## Warning in library(package, lib.loc = lib.loc, character.only = TRUE,
## logical.return = TRUE, : there is no package called 'ggplot'
## Loading required package: raster
## Loading required package: sp
## Loading required package: sudoku
## Warning in library(package, lib.loc = lib.loc, character.only = TRUE,
## logical.return = TRUE, : there is no package called 'sudoku'
## [[1]]
## [1] FALSE
## 
## [[2]]
## [1] TRUE
## 
## [[3]]
## [1] TRUE
## 
## [[4]]
## [1] FALSE
sapply(paquetes,require,character.only=TRUE)
## Loading required package: ggplot
## Warning in library(package, lib.loc = lib.loc, character.only = TRUE,
## logical.return = TRUE, : there is no package called 'ggplot'
## Loading required package: sudoku
## Warning in library(package, lib.loc = lib.loc, character.only = TRUE,
## logical.return = TRUE, : there is no package called 'sudoku'
## ggplot raster     sp sudoku 
##  FALSE   TRUE   TRUE  FALSE

El resultado que obtengo es el siguiente: lapply me devuelve en una lista qué paquetes ha podido cargar y cuáles no. sapply igual, pero de una manera un poco más limpia, lo mismo. El paquete ggplot no existe, pues se llama en realidad ggplot2. El paquete sudoku no lo tengo instalado.

Finalmente, vamos a utilizar sapply con nuesta función creada en el tema anterior ’mauna_analysis()`:

años<-c(1987,2001,1981,2014)

sapply(años,mauna_analysis)