Notas <- list(alumno1=c(2.5,3.7,6), alumno2=c(5,6.7,10))
Notas
medias <- lapply(Notas,mean)
medias
class(medias)3 Programación funcional
3.1 Familia apply
Una función de orden superior es una función que como argumento usa otra función. Son una alternativa para los bucles y trabajan vectorialemente con los datos, así que además de buscar una mayor belleza matemática en tu código, conseguiremos mayor eficiencia.
Tu puedes implementar funciones de orden superior, pero por ahora vamos a aprender a usar la familia de funciones apply:
- lapply
- sapply
- tapply
- apply
- etc.
Cogen una función como entrada y devuelven un vector.
3.1.1 lapply
Va tomando cada elemento de una lista, evalúa la función que aparece al final de lapply a cada elemento seleccionado de la lista y devuelve una lista con todos los resultados.
Ejecuta:
Como ves tenemos como resultado una lista con la media de cada una de los vectores que contiene la lista de entrada.
Simplemente otro ejemplo:
alumnos <- c("JUAN","PEDRO","ISABEL","LUISA")
alumnos.minus <-lapply(alumnos, tolower)
alumnos.minus[[1]]
[1] "juan"
[[2]]
[1] "pedro"
[[3]]
[1] "isabel"
[[4]]
[1] "luisa"
class(alumnos.minus)[1] "list"
3.1.2 sapply
Toma como entrada una lista y:
- Itera sobre cada elemento de la lista.
- Aplica una función \(f\) a cada elemento \(x\) de la lista.
- Devuelve un vector si cada \(f(x)\) tiene longitud 1.
- Devuelve una matriz si cada \(f(x)\) tiene longitud mayor que 1.
Veamos un par de ejemplos para entender cómo funciona.
Notas <- list(alumno1=c(2.5,3.7,6), alumno2=c(5,6.7,10))
Notas
medias <- sapply(Notas,mean)
medias
class(medias)En este caso, ves que devuelve un vector.
Usaremos sapply con un dataset que se almacenará en R en un data.frame.
Ejecuta:
data("airquality")
View(airquality)
sapply(airquality, mean)Calculamos con sapply la media para cada columna.
Pregunta: ¿Porque me ha devuelto para las dos primeras columnas el valor NA? Arréglalo.
3.1.3 tapply
Aplica una función a subconjuntos de un vector. Es útil cuando tienes que romper un vector en grupos y a cada grupo aplicarle una función.
En el dataset anterior airquality una columna tiene los meses. Calcularemos la media de la temperatura para cada uno de los meses:
tapply(airquality$Temp,airquality$Month, mean) 5 6 7 8 9
65.54839 79.10000 83.90323 83.96774 76.90000
3.1.4 apply
Aplica una función \(f\) a cada elemento sobre una dimensión de una matriz.
M <- matrix(rnorm(100),10,10)
apply(M,1,mean) ## Calcula la media de cada fila de la matriz
apply(M,2,mean) ## Calcula la media de cada columna de la matriz
apply(M,1,sum) ## Calcula la suma de cada fila de la matriz
apply(M,2,sum) ## Calcula la suma de cada columna de la matriz3.1.5 split
- split coge un objeto (vector, data frame, etc. ) y lo divide en grupos determinados por una variable de tipo factor.
- Usado en combinación con sapply, tapply (paradigma map-reduce ).
v <-1:100
f <- gl(10,10) ## consulta ayuda de gl ( >?gl )
split(v,f)
lapply(split(v,f), mean)
#con data frames
library(datasets)
head(airquality)
s <- split(airquality, airquality$Month)
lapply(s,function(x) mean(x[,"Wind"]) )3.1.6 Funciones anónimas
Se usan funciones anónimas (sin nombre) dentro de otras funciones, cuando su importancia no es muy grande o cuando solo se va a usar dentro de la función en la que está encerrada.
Ejemplo:
sin_cos <- function(parametro) {
if (parametro==0)
function(x) sin(x)
else
function(x) cos(x)
}#end function
sin1 <- sin_cos(0)
cos1 <- sin_cos(1)Ahora podemos usar sin1 y cos1 como funciones.
sin1(pi)[1] 1.224647e-16
cos1(pi)[1] -1
Cuando ejecutamos sin1 sin argumentos aparece:
sin1function(x) sin(x)
<environment: 0x10a586e00>
que indica que sin1 es la función sin(x).
Más adelante veremos la utilidad de estas funciones. Por ahora otro ejemplo.
Un ejemplo más usado, una función anónima dentro de lapply.
x <- 1:10
funs <- list(
sum = sum,
mean = mean,
median = median
)
lapply(funs, function(f) f(x))$sum
[1] 55
$mean
[1] 5.5
$median
[1] 5.5
f va tomando como valores las distintas funciones que hay almacenadas en la lista funs. Es decir, aplicamos la suma, la media y la mediana al vector x.
3.1.7 map
Es una función del paquete purr. Debes instalarlo la primera vez que lo uses.
La función map transforma su entrada aplicándole una función a cada elemento y devolviendo un vector con la misma longitud que la entrada.
Ejecuta:
library(purrr)# Instalar la primera vez
data("airquality")
View(airquality)
map(airquality,sum)El código anterior con la filosofia tidyverse (tuberías) aparecerá como:
library(magrittr);library(purrr)
Attaching package: 'purrr'
The following object is masked from 'package:magrittr':
set_names
airquality %>% map(sum)$Ozone
[1] NA
$Solar.R
[1] NA
$Wind
[1] 1523.5
$Temp
[1] 11916
$Month
[1] 1070
$Day
[1] 2418
3.2 Ejercicios
3.2.1 1. Funciones apply con listas
Dada la siguiente lista con nombre lista1 que debes introducir en R:
La lista nombrada lista1 es:
$notas_grupo1
[1] 1 2 3 4 5 7 6 5 4 3
$notas_grupo2_3
[,1] [,2] [,3]
[1,] 2 2 8
[2,] 3 9 8
La estructura de la lista es:
List of 2
$ notas_grupo1 : int [1:10] 1 2 3 4 5 7 6 5 4 3
$ notas_grupo2_3: num [1:2, 1:3] 2 3 2 9 8 8
Resuelve los siguientes ejercicios:
Usa
lapply()para encontrar la longitud de las notas de todos los grupos que están en lista1.Usa
sapply()para encontrar la media de las notas de todos los grupos que están en lista1.Usa
lapply()para encontrar los quantiles de las notas de todos los grupos que están en lista1.Dada la siguiente función \(f_1(x)=(3x)/10\), aplica \(f_1(x)\) a todas las notas para cambiar las puntuaciones a la escala de 1 a 3.
Repite el ejercicio 4 pero haciendo que \(f_1(x)\) sea una función anónima dentro de
lapply().Encuentra los valores no repetidos de las notas
Convierte todas las notas de la lista a un vector (aplana los valores).