Capítulo 6 Vectores
Scripts usados:
Hemos visto ya como poder almacenar elementos individuales como la edad de una persona (edad <- 32
) o su nombre (nombre <- "Javi"
). ¿Y si en lugar de querer almacenar un solo elemento, por ejemplo , tenemos una colección de elementos (las edades de toda nuestra familia, por ejemplo)?
En este capítulo vamos a ver un clásico de cualquier lenguaje de programación: los vectores o arrays, que no son más que una concatenación de elementos del mismo tipo. De hecho un número individual (por ejemplo, x <- 1
) es en realidad un vector de longitud uno (un solo elemento). Es el tipo de dato que más vas a usar ya que las columnas de cualquier tabla funcionarán como una concatenación de valores.
Un vector es lo que solemos representar como \(\overrightarrow{x} = \left[1, 2, 3 \right]\) en matemáticas, pero no te preocupes si nunca has visto esta forma de representarlos. Vamos a empezar de cero.
6.1 Vectores numéricos
La forma más sencilla de crear un vector en R
es con el comando c()
(para acordarte: letra c
de Concatenar), y basta con introducir sus elementos entre paréntesis, y separados por comas. Por ejemplo, supongamos que queremos guardar la edad de 4 personas (como si tuvieramos una columna edad
en una tabla de 4 filas).
edades <- c(32, 27, 60, 61)
edades
## [1] 32 27 60 61
Como ves ahora en el environment (el entorno, arriba a la derecha) tenemos una colección de elementos guardada, con cuatro elementos en concreto, almacenados en una misma variable edades
.
La longitud de un vector se puede calcular con el comando length()
(nos devolverá el número de elementos de la variable que le pasemos como argumento).
length(edades)
## [1] 4
Además podemos concatenar a su vez vectores (uno tras otro): vamos a concatenar el vector edades
consigo mismo, y añadiéndole al final un 8.
c(edades, edades, 8)
## [1] 32 27 60 61 32 27 60 61 8
Esta última concatenación lo que nos ha dado son, primero, los cuatro elementos que ya teníamos en edades
, después de nuevo los cuatro elementos, y por último un 8.
6.2 Secuencias numéricas con un patrón
En muchas ocasiones querremos crear vectores numéricos de una forma mucho más rápida. Supongamos que queremos un vector que nos almacene el número del mes, desde el 1 hasta el 31. Si construyéramos el vector como antes, tendríamos que ejecutar el comando c(1, 2, 3, 4, 5, ...)
hasta llegar al número 31. ¿Un poco largo, no?
Hay un atajo: el comando seq()
nos permite crear una secuencia desde un elemento inicial hasta un elemento final, avanzando de uno en uno.
seq(1, 31) # secuencia desde 1 hasta 31 de uno en uno
## [1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
## [26] 26 27 28 29 30 31
Es importante que no perdamos el foco: programar es similar a escribir en un idioma, por lo que si hay algo que se puede decir de una forma más limpia y que se entienda mejor, ¿por qué no usarlo? Siempre que queramos definir secuencias entre dos números naturales (por ejemplo, entre 1
y un valor n
), cuya distancia entre elementos consecutivos sea uno, el comando 1:n
nos devuelve lo mismo que la orden seq(1, n)
. Además, si el elemento inicial es mayor que el final, R
entenderá solo que la secuencia la queremos decreciente.
n <- 31
1:n # secuencia desde 1 hasta n (31) de uno en uno
## [1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
## [26] 26 27 28 29 30 31
n:1 # secuencia decreciente
## [1] 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7
## [26] 6 5 4 3 2 1
También podemos definir otro tipo de distancia entre dos elementos consecutivos (distancia conocida como paso de discretización), por ejemplo de 0.5 en 0.5, o de 1.7 en 1.7
seq(1, 10, by = 0.5) # secuencia desde 1 a 10 de 0.5 en 0.5
## [1] 1.0 1.5 2.0 2.5 3.0 3.5 4.0 4.5 5.0 5.5 6.0 6.5 7.0 7.5 8.0
## [16] 8.5 9.0 9.5 10.0
seq(1, 21, by = 1.7) # secuencia desde 1 a 21 de 1.7 en 1.7
## [1] 1.0 2.7 4.4 6.1 7.8 9.5 11.2 12.9 14.6 16.3 18.0 19.7
Otras veces nos interesará definir una secuencia entre un valor inicial y un valor final, pero nos dará igual la distancia entre cada elemento: solo nos importa que tenga un número concreto de elementos (y que sea R
el que decida la distancia entre elementos consecutivos para conseguirlo).
seq(1, 50, l = 11) # secuencia desde 1 a 50 de longitud 11
## [1] 1.0 5.9 10.8 15.7 20.6 25.5 30.4 35.3 40.2 45.1 50.0
seq(1, 50, l = 8) # secuencia desde 1 a 50 de longitud 8
## [1] 1 8 15 22 29 36 43 50
Otro atajo que podemos usar para definir secuencias de números con un patrón es definir vectores de elementos repetidos, por ejemplo un vector lleno de ceros. La función rep()
nos permite repetir un elemento un número fijado de veces.
rep(0, 7) # vector de 7 ceros
## [1] 0 0 0 0 0 0 0
No solo podemos repetir un número sino que podemos repetir vectores enteros.
## [1] 0 1 2 0 1 2 0 1 2 0 1 2
Esa repetición además podemos definirla también de forma intercalada: en lugar de repetir c(0, 1, 2)
cuatro veces seguidas, queremos cuatro 0, después cuatro 1, y después cuatro 2.
## [1] 0 0 0 0 1 1 1 1 2 2 2 2
6.3 Vectores de caracteres (texto)
Un error común es asociar el concepto de vectores solo a números: un vector es una colección o concatenación de elementos del mismo tipo, pero no tienen porque ser necesariamente números. Vamos a crear una frase de ejemplo, un vector de 4 elementos de tipo texto (en R
se llaman char
): "Mi"
, "nombre"
, "es"
"Javier"
.
Como antes, las variables de tipo char
o character
van entre comillas dobles, ya que es un cadena de texto.
mi_nombre <- c("Mi", "nombre", "es", "Javier")
mi_nombre
## [1] "Mi" "nombre" "es" "Javier"
Fíjate la diferencia entre tenerlo guardado en un vector o tenerlo como una cadena unida
variable <- "Mi nombre es Javier"
class(variable)
## [1] "character"
str_length(variable)
## [1] 19
## [1] "character"
str_length(vector)
## [1] 2 6 2 6
Cuando aplicamos la función str_length()
a un vector de caracteres, del paquete stringr que hemos visto en el tema anterior, la función se aplica A CADA ELEMENTO del vector (dándonos un vector de longitudes, de cada cadena que tenemos concatenada en el vector). Lo veremos con más detalle en el próximo tema.
str_to_lower(vector)
## [1] "mi" "nombre" "es" "javier"
str_detect(vector, "i") # TRUE --> si tiene letra i
## [1] TRUE FALSE FALSE TRUE
Ya tenemos nuestro primer vector de texto de longitud 4, y en cada elemento tenemos un texto. Cuando usamos la función paste()
con variables diferentes, usábamos sep = ...
para decidir el caracter con el que pegamos dichas cadenas texto. Cuando la función paste()
la aplicamos a un vector de caracteres, decidiremos que caracter queremos que vaya entre palabra con el argumento collapse =
.
paste(mi_nombre, collapse = "") # todo junto
## [1] "MinombreesJavier"
paste(mi_nombre, collapse = " ") # separados por un espacio
## [1] "Mi nombre es Javier"
paste(mi_nombre, collapse = ".") # separados por un punto .
## [1] "Mi.nombre.es.Javier"
paste0(mi_nombre) # todo junto sin nada separando
## [1] "Mi" "nombre" "es" "Javier"
Ahora que sabemos lo que es un vector de números, por ejemplo el vector 1:7
(el conjunto de naturales desde el 1 hasta el 7), podemos definir cadenas de texto que compartan por ejemplo un prefijo (persona_1
, persona_2
, …)
paste0("persona", 1:7) # a la palabra «persona» le pegamos los números del 1 al 7
## [1] "persona1" "persona2" "persona3" "persona4" "persona5" "persona6" "persona7"
paste("persona", 1:7, sep = "_") # separado por una barra baja
## [1] "persona_1" "persona_2" "persona_3" "persona_4" "persona_5" "persona_6"
## [7] "persona_7"
De igual manera podemos hacer uso del ya conocido paquete glue, combinando cadenas de texto y vectores numéricos, obteniendo vectores de frases.
## La edad es de 10 años
## La edad es de 11 años
## La edad es de 12 años
## La edad es de 13 años
# Otra forma sin definir variables a priori
glue("La edad es de {10:13} años")
## La edad es de 10 años
## La edad es de 11 años
## La edad es de 12 años
## La edad es de 13 años
6.4 Vectores lógicos (TRUE/FALSE)
[X] Variables numéricas (individuales) [X] Vectores de números [X] Vectores de caracteres [ ] Vectores lógicos
Veamos un último tipo de vectores muy importante en todo lenguaje de programación: los vectores de valores lógicos. Un valor lógico puede tomar tres valores:
-
TRUE
(guardado internamente como un 1). -
FALSE
(guardado internamente como un 0). -
NA
(dato ausente, son las siglas de not available, cuando pretendemos aplicar una comparación a un dato ya de por si ausente).
Los valores lógicos suelen ser resultado de evaluar condiciones lógicas, de hacerle preguntas a los datos. Por ejemplo, imaginemos que definimos un vector de temperaturas x <- c(15, 20, 23, 31, 27, 7, 29, 10)
. ¿Qué días hizo menos de 22 grados? Basta con que ejecutemos la orden x < 22
, que nos devolverá TRUE
o FALSE
en cada hueco, en función de si cumple (TRUE
) o no (FALSE
) la condición pedida.
x <- c(15, 20, 23, 31, 27, 7, 29, 10)
x < 22
## [1] TRUE TRUE FALSE FALSE FALSE TRUE FALSE TRUE
El primer, segundo, sexto y octavo día, la temperatura fue inferior (estrictamente) a 22, de ahí que en el primer, segundo, sexto y octavo día elemento aparezca un TRUE
y en el resto un FALSE
. Es importante recordar que al evaluar una condición lógica sobre un vector, la salida sigue siendo un vector de la misma longitud pero con valores lógicos.
Dicha condición lógica puede hacerse con otros operadores como <=
(menor o igual), >
(mayor) o >=
(mayor igual).
x <= 22
## [1] TRUE TRUE FALSE FALSE FALSE TRUE FALSE TRUE
x > 30
## [1] FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE
x >= 15
## [1] TRUE TRUE TRUE TRUE TRUE FALSE TRUE FALSE
También podemos comparar si es igual a otro elemento, para lo que usaremos el operador ==
, pudiendo usar también su opuesto !=
(«distinto de»).
x == 15
## [1] TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
x != 15
## [1] FALSE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
Si tuviéramos un dato ausente (por error del aparato ese día), la condición evaluada también sería ausente
y <- c(15, 20, NA, 31, 27, 7, 29, 10)
y < 22
## [1] TRUE TRUE NA FALSE FALSE TRUE FALSE TRUE
Las condiciones pueden ser combinadas, principalmente de dos maneras:
Intersección: todas las condiciones concatenadas se deben cumplir (conjunción y, operador
&
) para devolver unTRUE
.Unión: basta con que una de las condiciones concatenadas se cumpla (conjunción o, operador
|
) para devolver unTRUE
.
Por ejemplo, vamos a calcular qué elementos del vector de temperaturas sean menores que 30 pero (y) mayores que 15
x < 30 & x > 15
## [1] FALSE TRUE TRUE FALSE TRUE FALSE TRUE FALSE
Fíjate lo que sucede si no lo pedimos como intersección (ambas deben cumplirse) sino como unión (basta con que alguna se cumple)
x < 30 | x > 15
## [1] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
6.5 Consejos
CONSEJOS
Expresiones regulares
Dentro del entorno de paquetes tidyverse, el paquete stringr permite un manejo más complejo de cadenas de texo (como el uso de expresiones regulares).
6.6 📝 Ejercicios
(haz click en las flechas para ver soluciones)
📝Ejercicio 1: modifica el código inferior para crear un vector de nombre
vector_num
que contenga los números 1, 5 y -7.
- Solución:
# Vector de números
vector_num <- c(1, 5, -7)
vector_num
## [1] 1 5 -7
# Vector de números
vector_num <- c(1)
vector_num
📝Ejercicio 2: define un vector que contenga los números 1, 10, -1 y 2, y guárdalo en una variable llamada
vector_num
.
- Solución:
# Vector de números
vector_num <- c(1, 10, -1, 2)
vector_num
## [1] 1 10 -1 2
📝Ejercicio 3: obtén la longitud del vector anterior
vector_num
.
- Solución:
# Longitud del vector
length(vector_num)
## [1] 4
📝Ejercicio 4: crea un vector con las palabras “Hola”, “me”, “llamo” (y tu nombre y apellidos), y pega luego sus elementos de forma que la frase esté correctamente escrita en castellano. Tras hacerlo, añade “y tengo 30 años”.
- Solución:
# Definiendo el vector
vector_char <- c("Hola", "me", "llamo", "Javier",
"Álvarez", "Liébana")
# Pegamos
frase <- paste(vector_char, collapse = " ")
frase
## [1] "Hola me llamo Javier Álvarez Liébana"
# Añadimos frase
glue("{frase} y tengo 30 años.")
## Hola me llamo Javier Álvarez Liébana y tengo 30 años.
# Otra forma
paste0(frase, " y tengo 30 años.")
## [1] "Hola me llamo Javier Álvarez Liébana y tengo 30 años."
# Otra forma
paste(frase, "y tengo 30 años.")
## [1] "Hola me llamo Javier Álvarez Liébana y tengo 30 años."
📝Ejercicio 5: el código inferior crea una secuencia de números, que empieza en
-1
, que acaba en 32
, y que va saltando de 2 en 2. Modíficalo para que haga el salto de 3 en 3 y guárdalo en una variable llamada secuencia
- Solución:
secuencia <- seq(-1, 32, by = 3)
secuencia
## [1] -1 2 5 8 11 14 17 20 23 26 29 32
length(secuencia) # longitud de la secuencia
## [1] 12
seq(-1, 32, by = 2)
📝Ejercicio 6: crea una secuencia de números, que empiece en
-1
, que acabe en 32
, y que tenga longitud 12.
- Solución:
secuencia <- seq(-1, 32, l = 12)
secuencia
## [1] -1 2 5 8 11 14 17 20 23 26 29 32
length(secuencia) # longitud de la secuencia
## [1] 12
📝Ejercicio 7: crea una secuencia que empiece en 1 y recorra todos los naturales hasta el 10. Después crea otra secuencia de longitud 7 que todos los números sean
3
.
- Solución:
1:10
## [1] 1 2 3 4 5 6 7 8 9 10
rep(3, 7) # secuencia repetida
## [1] 3 3 3 3 3 3 3
📝Ejercicio 8: crea una secuencia que repita 5 veces el patrón
1, 2, 3
. Después crea otra que repita dicho patrón pero de forma intercalada, con 5 veces 1
, después 5 veces 2
y después 5 veces 3
.
- Solución:
## [1] 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3
## [1] 1 1 1 1 1 2 2 2 2 2 3 3 3 3 3
📝Ejercicio 9: crea una variable
x <- c("oso pardo", "oso polar", "ballena", "grillo", "oso panda", "perro")
. Haciendo uso de str_length()
calcula la longitud de cada cadena de texto. Haciendo uso de str_detect()
detecta los animales que son un oso.
- Solución:
x <- c("oso pardo", "Oso polar", "ballena", "grillo", "OSO panda", "perro")
str_length(x) # longitud
## [1] 9 9 7 6 9 5
# OJO! antes hay que pasar todo a mayúscula o minúscula, nos da igual que sea oso, OSO, Oso, etc
str_detect(str_to_lower(x), "oso")
## [1] TRUE TRUE FALSE FALSE TRUE FALSE