2.4 Vectores

2.4.1 Declarando vectores

Para crear una variable que contiene múltiples valores requerimos la función de concatenación o c(). Esta función toma como argumentos los valores que queremos concatenar y crea un objeto o una estructura de datos llamada vector.

numeros <- c(45, 38, 90, 5, 20, 3)

También podemos crear vectores numéricos que contengan una secuencia de números enteros con el operador :

enteros <- 23:31
# [1] 23 24 25 26 27 28 29 30 31
enteros_back <- 45:39
# [1] 45 44 43 42 41 40 39

O utilizando la función seq(), en donde definimos el valor de inicio, el valor final y el incremento que requerimos

secuencia <- seq(from = 1.5, to = 3.75, by = 0.25)
# [1] 1.50 1.75 2.00 2.25 2.50 2.75 3.00 3.25 3.50 3.75

Además, existe la función rep() con la cual podemos repetir valores un cierto número de veces.

repeticiones <- rep(5, times = 5)
# [1] 5 5 5 5 5
repeticiones_str <- rep("hi", times = 3)
# [1] "hi" "hi" "hi"
repeticiones_vec <- rep(c(2, 12, 22, 32, 42), times = 2)
# [1]  2 12 22 32 42  2 12 22 32 42

Cuando el primer argumento de la función rep() es un vector, podemos especificar que cada uno de los elementos en el vector se repita each veces

repeticiones_each <- rep(c(1, 4, 6), each = 4)
#  [1] 1 1 1 1 4 4 4 4 6 6 6 6
repeticiones_mn <- rep(numeros, each = 2)
# [1] 45 45 38 38 90 90  5  5 20 20  3  3

Al ser de una sola dimensión, los vectores solamente tienen longitud, y la podemos conocer con la función length()

length(numeros)
## [1] 6

2.4.2 Accesando a los valores

Podemos extraer valores de un vector mediante sus índices. Es importante recordar que en R los índices comienzan en 1.

numeros
# [1] 45 38 90  5 20  3
numeros[3]
# [1] 90
numeros[2:5]
# [1] 2 3 4 5
numeros[c(1, 4, 6)]
# [1] 45  5  3

Otra de las características más importantes del lenguaje de programación R es que las operaciones están vectorizadas; es decir, no es necesario recorrer un arreglo para realizar sumas u otras operaciones ya que las operaciones se aplican a cada uno de sus elementos.

numeros * 3
# [1] 135 114 270  15  60   9
numeros + 5
# [1] 50 43 95 10 25  8
numeros + c(1,4)
# [1] 46 42 91  9 21  7

La última operación logra sumar cada elemento de los valores de dos arreglos ya que uno tiene un tamaño que es múltiplo del otro. Si intentamos esta operación para tamaños no múltiplos, obtenemos un warning.

numeros + c(1,4, 6, 8)
## Warning in numeros + c(1, 4, 6, 8): longer object length is not a multiple of
## shorter object length
## [1] 46 42 96 13 21  7

La vectorización funciona también para operaciones lógicas

numeros < 10 
# [1] FALSE FALSE FALSE  TRUE FALSE  TRUE
numeros %% 2 == 0
# [1] 50 43 95 10 25  8
numeros == 90
# [1] FALSE FALSE  TRUE FALSE FALSE FALSE

Y los resultados de dichas operaciones, es decir, vectores lógicos, pueden servir también para extraer valores de los arreglos.

numeros[numeros < 10]
# [1] 5 3
numeros[numeros %% 2 == 0]
# [1] 38 90 20
numeros[numeros == 90]
# 90

Por ejemplo, si tenemos un arreglo de días y queremos extraer los que corresponden a los días lunes y miércoles, es posible utilizar el operador OR (|) o utilizar la función %in%.

dias <- sample(c("lu", "ma", "mi", "ju", "vi"), 15, replace = TRUE)
dias
##  [1] "mi" "lu" "vi" "ma" "ma" "mi" "vi" "mi" "vi" "ju" "ma" "mi" "ma" "ju" "mi"
dias == "lu" | dias == "mi"
##  [1]  TRUE  TRUE FALSE FALSE FALSE  TRUE FALSE  TRUE FALSE FALSE FALSE  TRUE
## [13] FALSE FALSE  TRUE
dias %in% c("lu", "mi")
##  [1]  TRUE  TRUE FALSE FALSE FALSE  TRUE FALSE  TRUE FALSE FALSE FALSE  TRUE
## [13] FALSE FALSE  TRUE

La función which obtiene los índices de los elementos donde el el resultado de la comparación es TRUE.

which(numeros > 20)
## [1] 1 2 3

Para contar cuántos elementos resultan TRUE en la comparación, podemos obtener el tamaño del vector de índices o sumar los elementos del vector lógico resultante de la comparación, aprovechando su conversión a valores numéricos.

length(which(numeros > 20))
## [1] 3
sum(numeros > 20)
## [1] 3

Con la función all podemos saber si todos los valores pasan la comparación.

all(numeros > 10)
## [1] FALSE
all(numeros %% 2 == 0)
## [1] FALSE

Con any preguntamos si algunos de los valores pasan la comparación

any(numeros > 15)
## [1] TRUE
any(numeros == 90)
## [1] TRUE
any(numeros == 4)
## [1] FALSE

2.4.3 Coerción

Es muy importante considerar que los vectores son estructuras de datos homogéneas, es decir, todos sus elementos deben ser del mismo tipo. Si los elementos del vector no son del mismo tipo, ocurre una coerción, en donde se asigna a todos los elementos la clase más restrictiva posible, en el orden: logical -> integer -> numeric -> character

mis_valores <- c("rojo", 77, "blanco", 1, TRUE)
class(mis_valores)
# [1] "character"
mis_valores <- c(77, FALSE, 1, TRUE)
class(mis_valores)
# [1] "numeric"

Como ya se mencionó, el valor especial lógico NA, especifica ausencia de datos. Por ejemplo,si intentamos acceder a un índice que no existen en un arreglo.

numeros[1000]
# [1] NA
numeros[-3]
# [1] NA

Además, si tenemos un vector con valores NA, debemos tener cuidado al ejecutar las funciones numéricas y especificar de forma explícita que los valores NA no deben ser tomados en cuenta.

mis_na <- c(numeros[1:3], NA, numeros[4:5])
mean(mis_na)
# [1] NA
mean(mis_na, na.rm = TRUE)
# [1] 39.6

Y para extraer los valores del vector que no son NA, se hace subset con la función is.na() para formar un vector lógico.

mis_na[is.na(mis_na)]
# [1] 45 38 90  5 20