Ejercicio -> Temperatura Farenheit ¿Quién no ha tenido problemas para entender las temperaturas en Farenheit?
Hoy crearan una formula para dejar de sufrir con este tema.
Primero, encontremos la formula que nos lleva de Farenheit a centigrados: * F 14º = C -10º * F 32º = C 0º * F 59º = C 15º
fahrenheit_to_celsius <- function(temp_F) {
# ¿Qué debemos poner aquí?
}
Las estructuras de control en R le permiten controlar el flujo de ejecución de una serie de expresiones R. Básicamente, las estructuras de control le permiten poner algo de “lógica” en su código R, en lugar de simplemente ejecutar siempre el mismo código R cada vez. Las estructuras de control le permiten responder a entradas o características de los datos y ejecutar diferentes expresiones R según corresponda a las instrucciones entregadas.
¿Cuáles son las funciones de control que existe?
if - elseif - else if - elseforwhileif - elseLa combinación `if - else es probablemente la estructura de control más utilizada en R (o quizás en cualquier lenguaje). Esta estructura le permite probar una condición y actuar en función de si es verdadera o falsa.
if - else: La condicion realiza una accion cuando es verdad y otra cuando es falsoif(<condition>) {
## do something
#}
else {
## do something else
#}
## Error: <text>:1:4: unexpected '<'
## 1: if(<
## ^
Ejemplo
quantity <- 15
# Set the is-else statement
if (quantity > 20) {
print('You sold a lot!')
} else {
print('Not enough for today')
}
## [1] "Not enough for today"
if - else if - else: Existen diversas condicionesif(<condition1>) {
## do something
} else if(<condition2>) {
## do something different
} else {
## do something different
}
## Error: <text>:1:4: unexpected '<'
## 1: if(<
## ^
Ejemplo
quantity <- 25
# Create multiple condition statement
if (quantity <20) {
print('Not enough for today')
} else if (quantity > 20 &quantity <= 30) {
print('Average day')
} else {
print('What a great day!')
}
## [1] "Average day"
for.Su objetivo es ejecutar un loop una cantidad fija de veces.
For simplefor (variable in secuencia) {
#"expresion"
}
## Error in eval(expr, envir, enclos): object 'secuencia' not found
Ejemplo
for(i in 2000:2010) {
print(i)
}
## [1] 2000
## [1] 2001
## [1] 2002
## [1] 2003
## [1] 2004
## [1] 2005
## [1] 2006
## [1] 2007
## [1] 2008
## [1] 2009
## [1] 2010
x <- c("a", "b", "c", "d")
for(i in 1:4) {
## Print out each element of 'x'
print(x[i])
}
## [1] "a"
## [1] "b"
## [1] "c"
## [1] "d"
for anidadoLos loops anidados son comúnmente necesarios para estructuras de datos multidimensionales o jerárquicas (por ejemplo, matrices, listas). Sin embargo, ten cuidado con la anidación. Anidar más allá de 2 a 3 niveles a menudo dificulta la lectura / comprensión del código
x <- matrix(1:6, 2, 3)
for(i in seq_len(nrow(x))) {
for(j in seq_len(ncol(x))) {
print(x[i, j])
}
}
## [1] 1
## [1] 3
## [1] 5
## [1] 2
## [1] 4
## [1] 6
whileSu objetivo es ejecutar un loop cuando se cumpla una condición.Mientras que los bucles comienzan probando una condición. Si es cierto, ejecutan el cuerpo del bucle. Una vez que se ejecuta el cuerpo del bucle, la condición se prueba nuevamente, y así sucesivamente, hasta que la condición sea falsa, después de lo cual se cierra el bucle.
#while (condition) {
# expression
#}
Ejemplo
count <- 0
while(count < 10) {
print(count)
count <- count + 1
}
## [1] 0
## [1] 1
## [1] 2
## [1] 3
## [1] 4
## [1] 5
## [1] 6
## [1] 7
## [1] 8
## [1] 9
Hay ciertas situaciones donde no voy a querer que el loop realize todas las iteraciones. En esos casos, me sirve realizar un Break o Next Statement.
break statement.Es una forma de salida de la rutina.
number <- 1:10
for (val in number) {
if (val == 5) {
print(paste("El loop terminara en el valor = ", val))
break
}
print(paste("El valor es : ", val))
}
## [1] "El valor es : 1"
## [1] "El valor es : 2"
## [1] "El valor es : 3"
## [1] "El valor es : 4"
## [1] "El loop terminara en el valor = 5"
Ejemplo 2
number <- 10
while (number > 0) {
if (number == 3) {
print(paste("Coming out from While loop Where number = ", number))
break
}
print(paste("Values are : ", number))
number = number - 1
}
## [1] "Values are : 10"
## [1] "Values are : 9"
## [1] "Values are : 8"
## [1] "Values are : 7"
## [1] "Values are : 6"
## [1] "Values are : 5"
## [1] "Values are : 4"
## [1] "Coming out from While loop Where number = 3"
next statement.Permite seguir la interccion pero saltanto algun elemento sin terminarlo.
x <- 1:5
for (val in x) {
if (val == 5){
next
}
print(val)
}
## [1] 1
## [1] 2
## [1] 3
## [1] 4
if# micr
micr <- 105.67
# Veamos
if (micr < 55) { # aquí la condición es que micr sea menos de 55
print("Comprar!") # cp,`rar
} else if ( micr >= 55 & micr < 75 ) { # aqui la condición es que micr este sea 55 o mas, o menos de 75
print("Hacer Nada!")
} else (micr >= 75) { # aquí es en el caso que micr sea mayor igual a 75
print("vender!") }
## Error: <text>:9:23: unexpected '{'
## 8: print("Hacer Nada!")
## 9: } else (micr >= 75) {
## ^
while# Crear la variable speed
speed <- 64
# Trabajemos un while con varias capas
while (){ # mientras la velocidad sea mayor a 30
print(paste("Tu velocidad es",speed))
if () { # la velocdad es mayor a 48
print(paste("Reduce la velocidad de inmediato!"))
speed <- speed # restemos 11 a la velocidad
} else {
print(paste("Baja la velocidad!"))
speed <- speed # restemos 6 a velocidad
}
}
## Error: <text>:5:8: unexpected ')'
## 4: # Trabajemos un while con varias capas
## 5: while ()
## ^
La familia de funciones apply es usada para aplicar una función a cada elemento de una estructura de datos. En particular, es usada para aplicar funciones en matrices, data frames, arrays y listas.
Con esta familia de funciones podemos automatizar tareas complejas usando poca líneas de código y es una de las características distintivas de R como lenguaje de programación.
apply()La función apply() toma un array o (en el caso de un 2D array tenemos una matriz) como entrada y entrega un vector, lista o matriz. Se usa principalmente para evitar usos explícitos de loops.
apply(X, MARGIN, FUN)
Como vemos arriba apply() tiene tres argumentos:
X: Una matriz o un objeto que pueda coercionarse a una matriz, generalmente, un data frame.MARGIN: La dimensión (margen) que agrupará los elementos de la matriz X, para aplicarles una función. Son identificadas con números, 1 son filas y 2 son colummnas.FUN: La función que aplicaremos a la matriz X en su dimención MARGIN.# Creemos una Matriz de 5x6
X <- matrix(1:30, nrow=5, ncol=6)
# Sumemos los valores de cada columna con apply()
apply(X, 2, FUN = sum)
## [1] 15 40 65 90 115 140
# Calculemos la media de cada fila con apply()
apply(X, 1,FUN = mean)
## [1] 13.5 14.5 15.5 16.5 17.5
FUN cuáles son sus argumentos?Recuerda que podemos llamar una función y proporcionar sus argumentos en orden, tal como fueron establecidos en su definición.
Por lo tanto, el primer argumento que espera la función, será la X del apply().
apply?En los casos en los que una función tiene recibe más de un argumento, asignamos los valores de estos del nombre de la función, separados por comas, usando sus propios nombres (a este procedimiento es al que se refiere el argumento … descrito en la documentación de apply).
Supongamos que deseamos encontrar los cuantiles de un vector, correspondientes a las probabilidades .33 y .66. Esto es definido con el argumento probs de esta función.
Para ello, usamos quantile() y después de haber escrito el nombre de la función, escribimos el nombre del argumento probs y los valores que deseamos para este.
apply(X, MARGIN = 2, FUN = quantile, probs = c(.33, .66))
## [,1] [,2] [,3] [,4] [,5] [,6]
## 33% 2.32 7.32 12.32 17.32 22.32 27.32
## 66% 3.64 8.64 13.64 18.64 23.64 28.64
Como podrás ver, hemos obtenido los resultados esperados.
lapply()lapply() es un caso especial de apply(), diseñado para aplicar funciones a todos los elementos de una lista. La l de su nombre se refiere, precisamente, a lista.
lapply() intentará coercionar a una lista el objeto que demos como argumento y después aplicará una función a todos sus elementos.
lapply() siempre nos devolverá una lista como resultado. A diferencia de apply(), sabemos que siempre obtendremos un objeto de tipo lista después de aplicar una función, sin importar cuál función sea.
Dado que en R todas las estructuras de datos pueden coercionarse a una lista, lapply() puede usarse en un número más amplio de casos que apply(), además de que esto nos permite utilizar funciones que aceptan argumentos distintos a vectores.
La estructura de esta función es:
lapply(X, FUN)
En donde:
X es una lista o un objeto coercionable a una lista.FUN es la función a aplicar.Estos argumentos son idéntico a los de apply(), pero a diferencia aquí no especificamos MARGIN, pues las listas son estructuras unidimensionales, es decir, solo tienen largo.
Probemos lapply() aplicando una función a un data frame. Usaremos el conjunto de datos trees, incluido por defecto en R base.
trees contiene datos sobre el grueso, alto y volumen de distinto árboles de cerezo negro. Cada una de estas variables está almacenada en una columna del data frame.
# Veamos los primeros cinco renglones de trees.
trees[1:5, ]
Aplicamos la función mean(), usando su nombre.
lapply(X = trees, FUN = mean)
## $Girth
## [1] 13.24839
##
## $Height
## [1] 76
##
## $Volume
## [1] 30.17097
Dado que un data frame está formado por columnas y cada columna es un vector atómico, cuando usamos lapply(), la función es aplicada a cada columna. lapply(), a diferencia de apply() no puede aplicarse a renglones.
En este ejemplo, obtuvimos la media de grueso (Girth), alto (Height) y volumen (Volume), como una lista.
Verificamos que la clase de nuestro resultado es una lista con class().
arboles <- lapply(X = trees, FUN = mean)
class(arboles)
## [1] "list"
Esto es muy conveniente, pues la recomendación para almacenar datos en un data frame es que cada columna represente una variable y cada renglón un caso (por ejemplo, el enfoque tidy de Wickham (2014)). Por lo tanto, con lapply() podemos manipular y transformar datos, por variable.
Al igual que con apply(), podemos definir argumentos adicionales a las funciones que usemos, usando sus nombres, después del nombre de la función.
lapply(X = trees, FUN = quantile, probs = .8)
## $Girth
## 80%
## 16.3
##
## $Height
## 80%
## 81
##
## $Volume
## 80%
## 42.6
Si usamos lapply con una matriz, la función se aplicará a cada celda de la matriz, no a cada columna.
Creamos una matriz.
matriz <- matrix(1:9, ncol = 3)
# Resultado
matriz
## [,1] [,2] [,3]
## [1,] 1 4 7
## [2,] 2 5 8
## [3,] 3 6 9
#Llamamos a lapply().
lapply(matriz, quantile, probs = .8)
## [[1]]
## 80%
## 1
##
## [[2]]
## 80%
## 2
##
## [[3]]
## 80%
## 3
##
## [[4]]
## 80%
## 4
##
## [[5]]
## 80%
## 5
##
## [[6]]
## 80%
## 6
##
## [[7]]
## 80%
## 7
##
## [[8]]
## 80%
## 8
##
## [[9]]
## 80%
## 9
Para usar una matriz con lapply() y que la función se aplique a cada columna, primero la coercionamos a un data frame con la función `as.data.frame().
lapply(as.data.frame(matriz), quantile, probs = .8)
## $V1
## 80%
## 2.6
##
## $V2
## 80%
## 5.6
##
## $V3
## 80%
## 8.6
Si deseamos aplicar una función a los renglones de una matriz, una manera de lograr es transponer la matriz con t() y después coercionar a un data frame.
matriz_t <- t(matriz)
lapply(as.data.frame(matriz_t), quantile, probs = .8)
## $V1
## 80%
## 5.8
##
## $V2
## 80%
## 6.8
##
## $V3
## 80%
## 7.8
lapply() en lugar de un bucle forEn muchos casos es posible reemplazar un bucle for() por un lapply().
De hecho, lapply() está haciendo lo mismo que un for(), está iterando una operación en todos los elementos de una estructura de datos.
Por lo tanto, el siguiente código con un for():
mi_vector <- 6:12
resultado <- NULL
posicion <- 1
for(numero in mi_vector) {
resultado[posicion] <- sqrt(numero)
posicion <- posicion + 1
}
resultado
## [1] 2.449490 2.645751 2.828427 3.000000 3.162278 3.316625 3.464102
Esto nos dará los mismos resultados que el siguiente código con lapply().
resultado <- NULL
resultado <- lapply(mi_vector, sqrt)
resultado
## [[1]]
## [1] 2.44949
##
## [[2]]
## [1] 2.645751
##
## [[3]]
## [1] 2.828427
##
## [[4]]
## [1] 3
##
## [[5]]
## [1] 3.162278
##
## [[6]]
## [1] 3.316625
##
## [[7]]
## [1] 3.464102
El código con lapply() es mucho más breve y más sencillo de entender, al menos para otros usuarios de R.
El inconveniente es que obtenemos una lista como resultado en lugar de un vector, pero eso es fácil de resolver usando la función as.numeric() para hacer coerción a tipo numérico.
as.numeric(resultado)
## [1] 2.449490 2.645751 2.828427 3.000000 3.162278 3.316625 3.464102
lapply() con listasHasta hora hemos hablado de usar lapply() con objetos que pueden coercionarse a una lista, pero ¿qué pasa si usamos esta función con una lista que contiene a otros objetos?
Pues la función se aplicará a cada uno de ellos. Por lo tanto, así podemos utilizar funciones que acepten todo tipo de objetos como argumento. Incluso podemos aplicar funciones a listas recursivas, es decir, listas de listas.
Por ejemplo, obtendremos el coeficiente de correlación de cuatro data frames contenidos en una sola lista. Esto no es posible con apply(), porque sólo podemos usar funciones que aceptan vectores como argumentos, pero con lapply() no es ningún problema.
Empezaremos creando una lista de data frames. Para esto, usaremos las función rnorm(), que genera números al azar y set.seed(), para que obtengas los mismos resultados aquí mostrados.
rnorm() creara n números al azar (pseudoaleatorios, en realidad), sacados de una distribución normal con media 0 y desviación estandar 1. set.seed() es una función que “fija” los resultados de una generación de valores al azar. Cada que ejecutas rnorm() obtienes resultados diferentes, pero si das un número como argumento seed a set.seed(), siempre obtendrás los mismos números.
# Fijamos seed
set.seed(seed = 2018)
# Creamos una lista con tres data frames dentro
tablas <- list(
df1 = data.frame(a = rnorm(n = 5), b = rnorm(n = 5), c = rnorm(n = 5)),
df2 = data.frame(d = rnorm(n = 5), e = rnorm(n = 5), f = rnorm(n = 5)),
df3 = data.frame(g = rnorm(n = 5), h = rnorm(n = 5), i = rnorm(n = 5))
)
# Resultado
tablas
## $df1
## a b c
## 1 -0.42298398 -0.2647112 -0.6430347
## 2 -1.54987816 2.0994707 -1.0300287
## 3 -0.06442932 0.8633512 0.7124813
## 4 0.27088135 -0.6105871 -0.4457721
## 5 1.73528367 0.6370556 0.2489796
##
## $df2
## d e f
## 1 -1.0741940 1.2638637 -0.2401222
## 2 -1.8272617 0.2501979 -1.0586618
## 3 0.0154919 0.2581954 0.4194091
## 4 -1.6843613 1.7855342 -0.2709566
## 5 0.2044675 -1.2197058 -0.6318248
##
## $df3
## g h i
## 1 -0.2284119 -0.4897908 -0.3594423
## 2 1.1786797 1.4105216 -1.2995363
## 3 -0.2662727 -1.0752636 -0.8698701
## 4 0.5281408 0.2923947 1.0543623
## 5 -1.7686592 -0.2066645 -0.1486396
Para obtener el coeficiente de correlación usaremos la función cor().
Esta función acepta como argumento una data frame o una matriz. Con este objeto, calculará el coeficiente de correlación R de Pearson existente entre cada una de sus columnas. Como resultado obtendremos una matriz de correlación.
Por ejemplo, este es el resultado de aplicar cor() a iris.
cor(iris[1:4])
## Sepal.Length Sepal.Width Petal.Length Petal.Width
## Sepal.Length 1.0000000 -0.1175698 0.8717538 0.8179411
## Sepal.Width -0.1175698 1.0000000 -0.4284401 -0.3661259
## Petal.Length 0.8717538 -0.4284401 1.0000000 0.9628654
## Petal.Width 0.8179411 -0.3661259 0.9628654 1.0000000
Con lapply aplicaremos cor() a cada uno de los data frames contenidos en nuestra lista. El resultado será una lista de matrices de correlaciones.
Esto lo logramos con una línea de código.
lapply(X = tablas, FUN = cor)
## $df1
## a b c
## a 1.0000000 -0.4427336 0.6355358
## b -0.4427336 1.0000000 -0.1057007
## c 0.6355358 -0.1057007 1.0000000
##
## $df2
## d e f
## d 1.0000000 -0.6960942 0.4709283
## e -0.6960942 1.0000000 0.2624429
## f 0.4709283 0.2624429 1.0000000
##
## $df3
## g h i
## g 1.0000000 0.6228793 -0.1472657
## h 0.6228793 1.0000000 -0.1211321
## i -0.1472657 -0.1211321 1.0000000
De esta manera puedes manipular información de múltiples data frames, matrices o listas con muy pocas líneas de código y, en muchos casos, más rápidamente que con las alternativas existentes.
Finalmente, si asignamos los resultados de las última operación a un objeto, podemos usarlos y manipularlos de la misma manera que cualquier otra lista.
correlaciones <- lapply(tablas, cor)
# Extraemos el primer elemento de la lista
correlaciones[[1]]
## a b c
## a 1.0000000 -0.4427336 0.6355358
## b -0.4427336 1.0000000 -0.1057007
## c 0.6355358 -0.1057007 1.0000000
applyExisten más funciones dentro de la familia apply:
sapply()eapply()mapply()rapply()tapply()vapply()Estas las veremos más adelante. Pero si quieren investigar, aqui hay un link