Vectores

Creación de vectores

En R, un vector es una colección ordenada de objetos de un mismo tipo o clase. Aprender sobre la creación y manipulación de vectores es un paso fundamental para comprender la manipulación de objetos más complejos, por ejemplo, las tablas y las matrices. Esto se debe a que estos objetos son justamente una colección de vectores.

La forma más simple de crear un vector es mediante la función genérica c(), que simplemente combina los elementos indicados entre comas:

vec <- c(1, 2, 3)
vec
[1] 1 2 3

Es posible asignarles un nombre a cada elemento, lo cual puede ser útil en algunos contextos:

vec <- c(a = 1, b = 2, c = 3)
vec
a b c 
1 2 3 

Si quisiéramos averiguar qué clase de elementos contiene el vector, utilizamos la función class():

class(vec)
[1] "numeric"

En general, podemos utilizar la función str() para conocer la estructura (structure) de cualquier objeto de R, incluyendo vectores:

str(vec)
 Named num [1:3] 1 2 3
 - attr(*, "names")= chr [1:3] "a" "b" "c"

Un vector puede componerse de cinco clases principales de elementos:

numeric Contienen números reales (decimales). Por ejemplo: c(1.2, 1.5, 1.7).
integer Contienen números enteros. Debemos indicarse con la letra L luego del número. Por ejemplo: c(1L, -5L, 16L, 17L).
logical Contienen valores booleanos o lógicos. Por ejemplo: c(TRUE, FALSE, NA) o c(T, F, T).
character Contienen texto, el cual debe explicitarse con comillas simples o dobles. Por ejemplo: c("Algarrobo", "Quebracho", "Espinillo").
NULL Representa un objeto vacío. Se genera al crear el vector: vec <- NULL.

Recordemos que al crear un vector, este puede componerse de un solo tipo de elementos. Por ello, debemos tener cuidado a la hora de generar nuestros vectores, y asegurarnos de que estamos generando un vector con elementos de la clase deseada. El uso de vectores con elementos de una clase incorrecta es un error muy común en distintos contextos del flujo de trabajo. Por ejemplo:

vec <- c(1985, "Algarrobo", "Quebracho")
class(vec)
[1] "character"

Observamos que el vector generado es de clase character. A la hora de forzar una clase para los elementos de un vector, R asigna prioridad a ciertas clases sobre otras. Si bien es posible correr líneas de código como la anterior, en general no sería una buena práctica hacerlo. Mejor ser explícito!

El vector como factor

Otra clase importante para los elementos de un vector es factor. Sirve para definir un factor categórico, compuesto por niveles (los elementos distintos y únicos del vector), los cuales siguen un orden específico:

especies <- c("Algarrobo", "Quebracho", "Espinillo")
especies <- factor(especies)
especies
[1] Algarrobo Quebracho Espinillo
Levels: Algarrobo Espinillo Quebracho

Es posible cambiar el orden de los niveles, definiendo al factor con el argumento levels:

especies <- factor(especies, levels = c("Quebracho", "Espinillo", "Algarrobo"))
especies
[1] Algarrobo Quebracho Espinillo
Levels: Quebracho Espinillo Algarrobo

Funciones útiles para la creación de vectores

Durante nuestro trabajo, puede ser útil la creación de vectores que sigan una lógica determinada. Si queremos generar una secuencia de números enteros con incremento de a una unidad, el operador de secuencia : es el indicado, siguiendo la lógica “desde:hasta”:

suc <- 5:30
suc
 [1]  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
[26] 30

Para generar vectores con una lógica más compleja, las funciones seq() y rep() son adecuadas. La función seq() genera una sucesión de números (i.e. un vector de clase numeric o integer):

seq(from = 1, to = 10, by = 2)
[1] 1 3 5 7 9

Los argumentos from y to determinan respectivamente los valores mínimos y máximos de la secuencia, mientras que el argumento by determina el incremento de la secuencia. Otra forma de generar el mismo vector del ejemplo sería:

seq(from = 1, by = 2, length.out = 5)
[1] 1 3 5 7 9

El argumento length.out determina el número máximo de elementos que contendrá el vector.

Al correr la función con un único número, obtenemos una sucesión de números enteros, comenzando desde el 1:

seq(10)
 [1]  1  2  3  4  5  6  7  8  9 10

La función rep() genera un nuevo vector a partir de la repetición de los elementos de un vector dado:

especies <- c("Algarrobo", "Quebracho", "Espinillo")
vec_sp <- rep(x = especies, times = 2)
vec_sp
[1] "Algarrobo" "Quebracho" "Espinillo" "Algarrobo" "Quebracho" "Espinillo"

El argumento x recibe un vector dado, mientras que el argumento times indica la cantidad de veces que debe repetirse el vector dado. Otro argumento relevante de la función rep() es el argumento each:

vec_sp <- rep(x = especies, each = 3)
vec_sp
[1] "Algarrobo" "Algarrobo" "Algarrobo" "Quebracho" "Quebracho" "Quebracho"
[7] "Espinillo" "Espinillo" "Espinillo"

Aquí, each = 3 indica que cada elemento del vector en x debe repetirse 3 veces.

Otras funciones útiles

Además de las expuestas, existen numerosas funciones nativas de R para generar vectores. Entre ellas, podemos mencionar a sample(), la cual genera un vector con un subconjunto aleatorio de elementos a partir un vector dado; runif() y rnorm(), los cuales generan vectores de elementos provenientes de una distribución uniforme o normal, respectivamente. Por otro lado, las funciones letters() y LETTERS() generan vectores de letras en minúscula o mayúscula.

Ejercicio

Dado el vector c(8, 45, 9, 3, -2, 9, 7, 14, 45), explore qué hacen las siguientes funciones: length(), sort(), rev() y unique().

Vectores y expresiones lógicas

Ahora que aprendimos cómo generar un vector, veremos cómo se evalúan las expresiones lógicas en este contexto. Por ejemplo:

3 == 1:10
 [1] FALSE FALSE  TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE

Aquí, evaluamos si cada elemento del vector 1:10 es igual al número 3, indicando TRUE en dicho caso. En cambio, utilizando != obtenemos como resultado lo opuesto:

3 != 1:10
 [1]  TRUE  TRUE FALSE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE

Obviamente, los operadores relaciones también son válidos:

3 >= 1:10
 [1]  TRUE  TRUE  TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE

En el contexto de vectores, es muy útil el operador lógico %in%. Este operador devuelve TRUE para cada elemento a la izquierda, sólo si dicho elemento es encontrado en el vector indicado a la derecha del operador. Caso contrario, devuelve FALSE. Por ejemplo:

3 %in% 1:10
[1] TRUE

También es posible indicar más de un elemento a la izquierda del operador:

c(1, 2, 3) %in% 1:10
[1] TRUE TRUE TRUE

Por otro lado, las funciones all() y any() son muy utilizadas a la hora de evaluar vectores lógicos. Anteriormente, vimos que estas funciones sirven para evaluar varias condiciones al mismo tiempo, separadas por una coma. No obstante, también es posible indicarle directamente un vector lógico. En el contexto de vectores, la función all() devuelve TRUE si todos los elementos del vector lógico son TRUE, caso contrario devuelve FALSE. Por ejemplo

cond <- 11 > 1:10
all(cond)
[1] TRUE

En cambio, con solo haber un sólo elemento igual a FALSE, la función all() devuelve FALSE:

cond <- 10 > 1:10
all(cond)
[1] FALSE

La función any(), devuelve TRUE si al menos un elemento del vector lógico es TRUE:

cond <- 10 <= 1:10
any(cond)
[1] TRUE

Caso contrario, si todos los elementos son iguales a FALSE, any() devuelve FALSE:

cond <- 15 < 1:10
any(cond)
[1] FALSE

Finalmente, es útil aclarar que en el contexto de operaciones aritméticas, TRUE equivale a 1 y FALSE equivale a 0. Por ejemplo, sea la siguiente condición:

cond <- 5 >= 1:10
cond
 [1]  TRUE  TRUE  TRUE  TRUE  TRUE FALSE FALSE FALSE FALSE FALSE

Si sumamos los elementos del vector lógico, obtenemos lo siguiente:

sum(cond)
[1] 5

¿De qué sirve conocer esto? Quizás no le veamos utilidad ahora mismo, pero puede llegar a ser útil en el contexto de un trabajo más avanzado (por ejemplo, en el contexto de manipulación de tablas).

Manipulación de vectores

Un apartado fundamental para aprender a programar en R es la manipulación de vectores. En pocas palabras, nos referimos a generar un nuevo vector a partir de uno creado previamente, de manera tal que sirva para realizar una tarea específica. Este tipo de tareas será de gran utilidad a la hora de trabajar con tablas.

Dado un vector, interesa averiguar su contenido, lo cual lo podemos hacer simplemente imprimiendo el vector en la consola, o rescatando uno o más elementos a través de sus índices:

vec <- seq(from = -5, to = 5, by = 0.25)
vec[15]
[1] -1.5
vec[c(1, 5, 10)]
[1] -5.00 -4.00 -2.75
vec[13:18]
[1] -2.00 -1.75 -1.50 -1.25 -1.00 -0.75

Los corchetes [] indican que se seleccionará un subconjunto de elementos del vector. En la segunda línea del ejemplo, seleccionamos el elemento de índice 15. En la tercera línea de código, seleccionamos los elementos de índice 1, 5 y 10. En la cuarta línea de código, en cambio, seleccionamos los elementos 13 al 18 (i.e. índices).

Es posible excluir elementos con el símbolo -:

especies <- c("Algarrobo", "Quebracho", "Espinillo")
especies_sub <- especies[-2]
especies_sub
[1] "Algarrobo" "Espinillo"

Además de la posibilidad de indicar índices, es posible utilizar un vector lógico. Dicho vector puede generarse definiendo condiciones que los elementos deben cumplir.

cond1 <- vec > -2 & vec < 2
cond1
 [1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[13] FALSE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE
[25]  TRUE  TRUE  TRUE  TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[37] FALSE FALSE FALSE FALSE FALSE
vec_sub <- vec[cond1]

Aquí, el objeto “cond1” es un vector lógico, indicando TRUE o FALSE para cada elemento del vector “vec”, según la condición expuesta: que el número sea mayor a -2 (vec > -2) y (&) menor a 2 (vec < 2). Notar que hay que ser explícito a la hora de definir la condición. Es útil indicar la condición directamente, sin necesidad de crear un objeto nuevo:

vec_sub <- vec[vec > -2 & vec < 2]
vec_sub
 [1] -1.75 -1.50 -1.25 -1.00 -0.75 -0.50 -0.25  0.00  0.25  0.50  0.75  1.00
[13]  1.25  1.50  1.75

La función subset() permite hacer la misma operación de filtrado, indicando el vector a filtrar, y la condición:

vec_sub <- subset(vec, vec > -2 & vec < 2)
vec_sub
 [1] -1.75 -1.50 -1.25 -1.00 -0.75 -0.50 -0.25  0.00  0.25  0.50  0.75  1.00
[13]  1.25  1.50  1.75

La función which() devuelve los índices de los elementos de un vector que cumplen con una condición dada:

which(vec > -2 & vec < 2)
 [1] 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28

Para pensar: Sin correr la expresión, ¿qué pasa si la condición que definimos es !(vec > -2 & vec < 2)?

Una vez seleccionado el subconjunto de elementos de un vector, es posible asignarle un valor diferente:

vec[vec <= 0] <- 0

Aquí, seleccionamos los valores menores o iguales a 0, y les asignamos el valor 0. Notar que en este caso, al ser un único valor de reemplazo, no es necesario repetir el 0 tantas veces como valores a reemplazar.

A veces, resulta útil reemplazar los valores NA (no dato) por algún otro valor útil, para lo cual podemos utilizar la función is.na().

vec <- c(5, 8, 16, NA, 3)
vec[is.na(vec)] <- 0
vec
[1]  5  8 16  0  3

En el contexto de valores NA, es útil la función na.omit(), que remueve todos los elementos que sean NA:

vec <- c(5, 8, 16, NA, 3, 8, NA)
vec2 <- na.omit(vec)
vec2
[1]  5  8 16  3  8
attr(,"na.action")
[1] 4 7
attr(,"class")
[1] "omit"

A la hora de efectuar subconjuntos de vectores, es importante diferenciar el uso del operador == del %in%, que ya introdujimos anteriormente. Al utilizar el operador == nos preguntamos si cada elemento del vector indicado a la izquierda del operador es igual al elemento (o a los elementos) indicado a la derecha; y utilizamos la expresión lógica resultante para hacer el subset del vector:

especies <- rep(c("Algarrobo", "Molle", "Quebracho", "Piquillin"), each = 5)
especies[especies == "Quebracho"]
[1] "Quebracho" "Quebracho" "Quebracho" "Quebracho" "Quebracho"

¿Cómo procedemos si, por ejemplo, quisiéramos seleccionar más de una especie? El operador == ya no es útil por sí solo. Una opción es la siguiente:

especies[especies == "Molle" | especies == "Piquillin"]
 [1] "Molle"     "Molle"     "Molle"     "Molle"     "Molle"     "Piquillin"
 [7] "Piquillin" "Piquillin" "Piquillin" "Piquillin"

Otra forma de hacerlo es utilizar el operador %in%. Recordemos que este operador indica TRUE o FALSE si cada elemento del vector a la izquierda está contenido en el vector indicado a la derecha:

especies[especies %in% c("Molle", "Piquillin")]
 [1] "Molle"     "Molle"     "Molle"     "Molle"     "Molle"     "Piquillin"
 [7] "Piquillin" "Piquillin" "Piquillin" "Piquillin"

Como veremos más adelante, el operador %in% es muy útil en el contexto de manipulación de tablas.

Es posible añadir elementos a un vector con la función c():

especies <- c("Algarrobo", "Quebracho", "Espinillo")
especies <- c(especies, "Yuchan", "Tusca")
especies
[1] "Algarrobo" "Quebracho" "Espinillo" "Yuchan"    "Tusca"    

Para explorar: La función append() es una forma general de hacer esto. Explore ?append.

Funciones básicas para vectores numéricos

Anteriormente, hemos visto cómo trabajan las funciones round(), ceiling(), floor() and trunc() con números sueltos. Sin embargo, estas funciones, al igual que muchas otras funciones nativas de R, son funciones vectorizadas. Esto significa que pueden trabajar sobre un vector, y arrojar un resultado para cada uno de los elementos del vector.

Por ejemplo:

vec <- c(1.233, 1.924, 0.46)
round(vec, digits = 1)
[1] 1.2 1.9 0.5

R también provee de numerosas funciones nativas para obtener medidas de resumen. Podemos mencionar a mean() para calcular el promedio, median() para calcular la mediana y sd() para calcular el desvío estándar.

Ejercicio final

  1. Utilice las funciones rep() y seq() para generar los siguientes vectores:
  • Una sucesión de números pares de 15 elementos.
  • Una sucesión de números decimales, con un incremento de 0.15.
  • Un vector tipo character, que indique 4 categorías discretas, repetidas de a 3 cada una.
  • Un vector que repita 5 veces el siguiente vector: c(F, T, F, T).
  1. Dado el vector seq(from = 0, to = 1, by = 0.01), y utilizando los aprendido sobre manipulación de vectores y expresiones lógicas, genere nuevos vectores de acuerdo a los siguientes criterios:
  • Que contenga los elementos de índices 10 a 20.
  • Que excluya los elementos 30 a 50. Ayuda: utilice paréntesis.
  • Que los elementos sean mayores a 0.5.
  • Que los elementos sean menores o iguales a 0.3 o mayores a 0.7.
  • Que los elementos cumplan con la condición opuesta a la inmediatamente anterior.
  1. Genere un vector de 500 números provenientes de una distribución normal, de media 15 y desvío estándar 4. Para ello, utilice la función rnorm() (explore la ayuda mediante ?rnorm). Seguidamente, verifique los valores de media, mediana y desvío estándar de la muestra. Calcule los cuantiles tradicionales mediante quantile(). Calcule el percentil 5% y el 95%.

Volver arriba