A.3 Cap. 5: Programación funcional
- Reproduce el resultado del siguiente loop
for, utilizando la funciónreplicate():
set.seed(123)
lista1 <- list() # Lista vacía
for (i in 1:3) { # Número de iteraciones = 5
lista1[[i]] = rnorm(6, 0, 1) # Conjunto aleatorio normal para cada iteración
}
lista1
# [[1]]
# [1] -0.56048 -0.23018 1.55871 0.07051 0.12929 1.71506
#
# [[2]]
# [1] 0.4609 -1.2651 -0.6869 -0.4457 1.2241 0.3598
#
# [[3]]
# [1] 0.4008 0.1107 -0.5558 1.7869 0.4979 -1.9666Solución:
# Importante simplify = FALSE para obtener una lista
# de vectores y no un solo vector con todos los resultados
set.seed(123)
lista1 <- replicate(3, {
rnorm(6, 0, 1)
},
simplify = FALSE)
### Resultado
lista1
# [[1]]
# [1] -0.56048 -0.23018 1.55871 0.07051 0.12929 1.71506
#
# [[2]]
# [1] 0.4609 -1.2651 -0.6869 -0.4457 1.2241 0.3598
#
# [[3]]
# [1] 0.4008 0.1107 -0.5558 1.7869 0.4979 -1.9666- Crea la base de datos DF numérica (código ya definido en el siguiente chunk), que tiene las dimensiones 12 (filas) x 5 (columnas). Esta base contiene valores no deseados:
-999. Crea y utiliza una función llamadacambiarNA()que te permita cambiar estos valores porNA.
# Base de datos DF
set.seed(123)
secuencia <- c(seq(0.5, 7.9, length = 10), -999, 5555)
DF <- data.frame(replicate(5,
sample(secuencia, 12, rep = TRUE)))
DF <- round(DF,2)
# Darle nombre a sus columnas
colnames(DF) <- paste0("Var", 1:5)
# Revisar el contenido de DF
DF
# Var1 Var2 Var3 Var4 Var5
# 1 2.14 3.79 7.08 7.90 6.26
# 2 2.14 2.14 2.14 5.43 5555.00
# 3 7.90 -999.00 2.97 -999.00 1.32
# 4 1.32 7.08 0.50 5555.00 0.50
# 5 4.61 5555.00 -999.00 3.79 7.08
# 6 -999.00 7.08 5.43 5.43 -999.00
# 7 3.79 7.08 3.79 3.79 7.08
# 8 2.97 2.14 5555.00 -999.00 4.61
# 9 4.61 6.26 7.90 4.61 3.79
# 10 7.08 7.90 5.43 7.08 7.08
# 11 7.90 5.43 7.08 1.32 7.90
# 12 -999.00 7.90 7.08 3.79 5555.00Solución:
### Crear función
cambiarNA <- function(x) {
x[x == -999] <- NA
print(x)
}
### Usar la función
cambiarNA(DF)
# Var1 Var2 Var3 Var4 Var5
# 1 2.14 3.79 7.08 7.90 6.26
# 2 2.14 2.14 2.14 5.43 5555.00
# 3 7.90 NA 2.97 NA 1.32
# 4 1.32 7.08 0.50 5555.00 0.50
# 5 4.61 5555.00 NA 3.79 7.08
# 6 NA 7.08 5.43 5.43 NA
# 7 3.79 7.08 3.79 3.79 7.08
# 8 2.97 2.14 5555.00 NA 4.61
# 9 4.61 6.26 7.90 4.61 3.79
# 10 7.08 7.90 5.43 7.08 7.08
# 11 7.90 5.43 7.08 1.32 7.90
# 12 NA 7.90 7.08 3.79 5555.00
### Para guardar sus resultados permanentemente
resultados <- cambiarNA(DF)
# Var1 Var2 Var3 Var4 Var5
# 1 2.14 3.79 7.08 7.90 6.26
# 2 2.14 2.14 2.14 5.43 5555.00
# 3 7.90 NA 2.97 NA 1.32
# 4 1.32 7.08 0.50 5555.00 0.50
# 5 4.61 5555.00 NA 3.79 7.08
# 6 NA 7.08 5.43 5.43 NA
# 7 3.79 7.08 3.79 3.79 7.08
# 8 2.97 2.14 5555.00 NA 4.61
# 9 4.61 6.26 7.90 4.61 3.79
# 10 7.08 7.90 5.43 7.08 7.08
# 11 7.90 5.43 7.08 1.32 7.90
# 12 NA 7.90 7.08 3.79 5555.00
resultados
# Var1 Var2 Var3 Var4 Var5
# 1 2.14 3.79 7.08 7.90 6.26
# 2 2.14 2.14 2.14 5.43 5555.00
# 3 7.90 NA 2.97 NA 1.32
# 4 1.32 7.08 0.50 5555.00 0.50
# 5 4.61 5555.00 NA 3.79 7.08
# 6 NA 7.08 5.43 5.43 NA
# 7 3.79 7.08 3.79 3.79 7.08
# 8 2.97 2.14 5555.00 NA 4.61
# 9 4.61 6.26 7.90 4.61 3.79
# 10 7.08 7.90 5.43 7.08 7.08
# 11 7.90 5.43 7.08 1.32 7.90
# 12 NA 7.90 7.08 3.79 5555.00- Utilizando la base de datos DF creada inicialmente en el ejercicio 2, modifica la función
cambiarNA()para que no solo cambie-999aNA, sino que cambie cualquier valor que tú le proporciones con un argumento. Llama a esta funcióncambiarNA2(). Utilízala para reemplazar los valores5555aNA.
Solución:
# Crear la función con un argumento extra que te
# permita modificar el número a reemplazar por NA
cambiarNA2 <- function(x, valor) {
x[x == valor] <- NA
print(x)
}
# Usar la función
cambiarNA2(DF, 5555)
# Var1 Var2 Var3 Var4 Var5
# 1 2.14 3.79 7.08 7.90 6.26
# 2 2.14 2.14 2.14 5.43 NA
# 3 7.90 -999.00 2.97 -999.00 1.32
# 4 1.32 7.08 0.50 NA 0.50
# 5 4.61 NA -999.00 3.79 7.08
# 6 -999.00 7.08 5.43 5.43 -999.00
# 7 3.79 7.08 3.79 3.79 7.08
# 8 2.97 2.14 NA -999.00 4.61
# 9 4.61 6.26 7.90 4.61 3.79
# 10 7.08 7.90 5.43 7.08 7.08
# 11 7.90 5.43 7.08 1.32 7.90
# 12 -999.00 7.90 7.08 3.79 NA- Utilizando la base de datos DF creada inicialmente en el ejercicio 2, modifica la función
cambiarNA2()de tal manera que te permita definir más de un valor (un vector numérico) como elementos a ser reemplazados porNA. Llama a esta funcióncambiarNA3(). Cambia porNAlos valores-999y5555. Pista: Esta función deberá contener un loop para aplicarle la función de cambio por NA a un elemento del vector a la vez en cada iteración.
Solución:
### Crear la función con un argumento que admita
### un vector de varios elementos a cambiar por NA
cambiarNA3 <- function(x, vector) {
for (i in seq_along(vector)) {
x[x == vector[i]] <- NA
}
print(x)
}
### Usar la función
cambiarNA3(DF, c(5555, -999))
# Var1 Var2 Var3 Var4 Var5
# 1 2.14 3.79 7.08 7.90 6.26
# 2 2.14 2.14 2.14 5.43 NA
# 3 7.90 NA 2.97 NA 1.32
# 4 1.32 7.08 0.50 NA 0.50
# 5 4.61 NA NA 3.79 7.08
# 6 NA 7.08 5.43 5.43 NA
# 7 3.79 7.08 3.79 3.79 7.08
# 8 2.97 2.14 NA NA 4.61
# 9 4.61 6.26 7.90 4.61 3.79
# 10 7.08 7.90 5.43 7.08 7.08
# 11 7.90 5.43 7.08 1.32 7.90
# 12 NA 7.90 7.08 3.79 NA- Crea un loop
forque itere sobre los números del 1 al 50 y calcule el cubo de cada número, de manera que los resultados se vayan guardando en un vector llamadopreliminar. Luego, crea un segundo loop que te permita identificar y almacenar solamente los números menores a la medianamedian()del conjunto de datospreliminaren un nuevo vector llamadofinal.
Solución:
### Secuencia numérica
secuencia <- 1:50
### Primer loop con for
preliminar <- c()
for(i in seq_along(secuencia)){
preliminar[i] <- secuencia[i]^3
}
### Resultado preliminar
preliminar
# [1] 1 8 27 64 125 216 343 512 729 1000 1331
# [12] 1728 2197 2744 3375 4096 4913 5832 6859 8000 9261 10648
# [23] 12167 13824 15625 17576 19683 21952 24389 27000 29791 32768 35937
# [34] 39304 42875 46656 50653 54872 59319 64000 68921 74088 79507 85184
# [45] 91125 97336 103823 110592 117649 125000
### Segundo loop con for
final <- c()
for( i in seq_along(preliminar)) {
if(preliminar[i] <= median(preliminar)){
final <- c(final, preliminar[i])
}
}
### Resultado final
final
# [1] 1 8 27 64 125 216 343 512 729 1000 1331 1728 2197
# [14] 2744 3375 4096 4913 5832 6859 8000 9261 10648 12167 13824 15625- En R ya existe una función para calcular la varianza y es
var(). Pero este ejercicio se trata de poner en juego lo que aprendiste sobre programación en R. La fórmula matemática de la varianza poblacional, con denominador \(n\), Ecuación (5.1). Pero la funciónvar()de R contiene la fórmula matemática para calcular la varianza de muestras, no de poblaciones enteras. La fórmula matemática de la varianza muestral que usa R tiene como denominador \(n-1\), Ecuación (5.2). Crea una función llamadavar2()que calcule la varianza del conjunto de datos llamadovector. Finalmente, compara tus resultados con los obtenidos porvar().
\[\begin{align} \sigma^2 = \frac{1}{n}*{\displaystyle\sum_{i=1}^{n}(x_i - \mu)^2} \tag{5.1} \end{align}\]
\[\begin{equation} \sigma^2 = \frac{1}{n-1}*{\displaystyle\sum_{i=1}^{n}(x_i - \mu)^2} \tag{5.2} \end{equation}\]
set.seed(123)
vector <- rnorm(50, 21, 1.6)Solución:
Dentro de la función necesitas:
- Un código que calcule el promedio de los valores de
vector. - Una estructura que le reste el promedio a cada elemento de
vectory eleve cada resta al cuadrado. - Sumar todos los cuadrados obtenidos.
- Identificar la longitud de
vector(denotada porn), y dividir la sumatoria de cuadrados entren.
### Crear la función
var2 <- function(x) {
promedio <- mean(x)
cuadrados <- c()
for(i in seq_along(x)) {
valor <- (x[i] - promedio)^2
cuadrados <- c(cuadrados, valor)
}
n <- length(x)
sumatoria <- sum(cuadrados)
varianza <- sumatoria / (n-1)
return(varianza)
}
### Usar la función
var2(vector)
# [1] 2.195
### Comparar con la el resultado de var()
var(vector)
# [1] 2.195Si necesitas en algún momento, ya conoces cómo crear la fórmula de la varianza poblacional en R.
- Carga la base de datos npk. Usando una función de la familia apply(), calcula la el promedio, mediana y desviación estándar de la columna
yieldpara cada categoría (numérica) de la columnablock. Con ello, se conocerá el promedio de producción que se obtuvo en cada bloque para un estudio de mejora fitogenética:
data("npk")Solución:
tapply(npk$yield, npk$block, FUN = mean)
# 1 2 3 4 5 6
# 54.02 57.45 60.77 50.12 50.52 56.35
tapply(npk$yield, npk$block, FUN = median)
# 1 2 3 4 5 6
# 53.25 57.25 59.30 47.15 50.65 56.60
tapply(npk$yield, npk$block, FUN = sd)
# 1 2 3 4 5 6
# 7.269 2.044 6.790 8.150 1.486 2.435- Ejecuta el siguiente código para crear una lista llamada
iris3Listaa partir de la base de datos de ejemploiris3(un array). Si revisasiris3Lista, notarás que continene 3 elementos, cada uno de ellos es una matriz de datos de cuatro columnas (Sepal L.,Sepal W.,Petal L., yPetal W.). Utilizando dos funciones de la familiaapply(), calcula el promedio de cada columna de cada elemento de la listairis3Lista.
### Cargar iris3
data("iris3")
### Convertirla a lista
iris3Lista <- list(setosa = iris3[,,1],
versicolor = iris3[,,2],
virginica = iris3[,,3])Solución:
lapply(iris3Lista, FUN = function(x) {
apply(x, 2, mean)
})
# $setosa
# Sepal L. Sepal W. Petal L. Petal W.
# 5.006 3.428 1.462 0.246
#
# $versicolor
# Sepal L. Sepal W. Petal L. Petal W.
# 5.936 2.770 4.260 1.326
#
# $virginica
# Sepal L. Sepal W. Petal L. Petal W.
# 6.588 2.974 5.552 2.026