Vectorización
Resumen
Enseñando: 10 min
Ejercicios: 15 minPreguntas
¿Cómo puedo operar sobre todos los elementos de un vector a la vez?
Objectivos
Entender las operaciones vertorizadas en R.
La mayoría de las funciones en R están vectorizadas, lo que significa que la función operará sobre todos los elementos de un vector sin necesidad de hacer un bucle a través de cada elemento y actuar sobre cada uno de ellos. Esto hace la escritura de código más concisa, fácil de leer y menos propenso a errores.
x <- 1:4
x * 2
[1] 2 4 6 8
La multiplicación se aplicó a cada elemento del vector.
También podemos sumar dos vectores juntos:
y <- 6:9
x + y
[1] 7 9 11 13
Cada elemento de x
fue sumado a su correspondiente elemento de y
:
x: 1 2 3 4
+ + + +
y: 6 7 8 9
---------------
7 9 11 13
Desafío 1
Probemos esto en la columna
pop
del datasetgapminder
.Haz una nueva columna en el data frame
gapminder
que contiene la población en unidades de millones de personas. Comprueba el principio o el final del data frame para asegurar que funcionó.Solución al desafío 1
Intenta esto en la columna
pop
del datasetgapminder
.Haz una nueva columna en el data frame
gapminder
que contiene población en unidades de millones de personas. Comprueba el principio o el final del data frame para asegurar que funcionó.gapminder$pop_millions <- gapminder$pop / 1e6 head(gapminder)
country year pop continent lifeExp gdpPercap pop_millions 1 Afghanistan 1952 8425333 Asia 28.801 779.4453 8.425333 2 Afghanistan 1957 9240934 Asia 30.332 820.8530 9.240934 3 Afghanistan 1962 10267083 Asia 31.997 853.1007 10.267083 4 Afghanistan 1967 11537966 Asia 34.020 836.1971 11.537966 5 Afghanistan 1972 13079460 Asia 36.088 739.9811 13.079460 6 Afghanistan 1977 14880372 Asia 38.438 786.1134 14.880372
Desafío 2
En una sola gráfica, traza la población, en millones, en comparación con el año, para todos los países. No te preocupes en identificar qué país es cuál.
Repite el ejercicio, graficando sólo para China, India, e Indonesia. Nuevamente, no te preocupes acerca de cuál es cuál.
Solución al desafío 2
Recuerda tus habilidades de graficación al crear una gráfica con la población en millones en comparación con el año.
ggplot(gapminder, aes(x = year, y = pop_millions)) + geom_point()
countryset <- c("China","India","Indonesia") ggplot(gapminder[gapminder$country %in% countryset,], aes(x = year, y = pop_millions)) + geom_point()
Operadores de comparación, operadores lógicos y muchas otras funciones también están vectorizadas:
Operadores de Comparación
x > 2
[1] FALSE FALSE TRUE TRUE
Operadores Lógicos
a <- x > 3 # or, for clarity, a <- (x > 3)
a
[1] FALSE FALSE FALSE TRUE
Sugerencia: algunas funciones útiles para vectores lógicos
any()
devuelveTRUE
si algún elemento del vector esTRUE
all()
devuelveTRUE
si todos los elementos del vector sonTRUE
La mayoría de las funciones también operan elemento por elemento en los vectores:
Funciones
x <- 1:4
log(x)
[1] 0.0000000 0.6931472 1.0986123 1.3862944
Operaciones vectorizadas en matrices:
m <- matrix(1:12, nrow=3, ncol=4)
m * -1
[,1] [,2] [,3] [,4]
[1,] -1 -4 -7 -10
[2,] -2 -5 -8 -11
[3,] -3 -6 -9 -12
Sugerencia: multiplicación elemento por elemento vs. multiplicación de matriz
Muy importante: el operador
*
te da una multiplicación de elemento por elemento! Para hacer multiplicación de matrices, necesitás usar el operador%*%
:m %*% matrix(1, nrow=4, ncol=1)
[,1] [1,] 22 [2,] 26 [3,] 30
matrix(1:4, nrow=1) %*% matrix(1:4, ncol=1)
[,1] [1,] 30
Para saber más sobre Álgebra de matrices, ver Quick-R reference guide
Desafío 3
Dada la siguiente matriz:
m <- matrix(1:12, nrow=3, ncol=4) m
[,1] [,2] [,3] [,4] [1,] 1 4 7 10 [2,] 2 5 8 11 [3,] 3 6 9 12
Escribe lo que crees que sucederá cuando se ejecute:
m ^ -1
m * c(1, 0, -1)
m > c(0, 20)
m * c(1, 0, -1, 2)
¿Obtuviste la salida que esperabas? Si no, pregunta a un ayudante!
Solución al desafío 3
Dada la siguiente matriz:
m <- matrix(1:12, nrow=3, ncol=4) m
[,1] [,2] [,3] [,4] [1,] 1 4 7 10 [2,] 2 5 8 11 [3,] 3 6 9 12
Escribe lo que piensas que sucederá cuando ejecutes:
m ^ -1
[,1] [,2] [,3] [,4] [1,] 1.0000000 0.2500000 0.1428571 0.10000000 [2,] 0.5000000 0.2000000 0.1250000 0.09090909 [3,] 0.3333333 0.1666667 0.1111111 0.08333333
m * c(1, 0, -1)
[,1] [,2] [,3] [,4] [1,] 1 4 7 10 [2,] 0 0 0 0 [3,] -3 -6 -9 -12
m > c(0, 20)
[,1] [,2] [,3] [,4] [1,] TRUE FALSE TRUE FALSE [2,] FALSE TRUE FALSE TRUE [3,] TRUE FALSE TRUE FALSE
Desafío 4
Estamos interesados en encontrar la suma de la siguiente secuencia de fracciones:
x = 1/(1^2) + 1/(2^2) + 1/(3^2) + ... + 1/(n^2)
Esto sería tedioso de escribir, e imposible para valores altos de n. Usa vectorización para calcular x cuando n=100. ¿Cuál es la suma cuando n=10.000?
Solución al desafío 4
Estamos interesados en encontrar la suma de la siguiente secuencia de fracciones:
x = 1/(1^2) + 1/(2^2) + 1/(3^2) + ... + 1/(n^2)
Esto sería tedioso de escribir, e imposible para valores altos de n. ¿Puedes usar vectorización para calcular x, cuando n=100? ¿Qué tal cuando n=10,000?
sum(1/(1:100)^2)
[1] 1.634984
sum(1/(1:1e04)^2)
[1] 1.644834
n <- 10000 sum(1/(1:n)^2)
[1] 1.644834
Podemos obtener el mismo resultado usando una función:
inverse_sum_of_squares <- function(n) { sum(1/(1:n)^2) } inverse_sum_of_squares(100)
[1] 1.634984
inverse_sum_of_squares(10000)
[1] 1.644834
n <- 10000 inverse_sum_of_squares(n)
[1] 1.644834
Puntos Clave
Uso de operaciones vectorizadas en lugar de bucles.