vec <- c(1, 2, 3)
vec[1] 1 2 3
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:
Es posible asignarles un nombre a cada elemento, lo cual puede ser útil en algunos contextos:
Si quisiéramos averiguar qué clase de elementos contiene el vector, utilizamos la función class():
En general, podemos utilizar la función str() para conocer la estructura (structure) de cualquier objeto de R, incluyendo vectores:
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:
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!
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:
[1] Algarrobo Quebracho Espinillo
Levels: Algarrobo Espinillo Quebracho
Es posible cambiar el orden de los niveles, definiendo al factor con el argumento levels:
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”:
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):
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:
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:
La función rep() genera un nuevo vector a partir de la repetición de los elementos de un vector dado:
[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:
[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.
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.
Dado el vector c(8, 45, 9, 3, -2, 9, 7, 14, 45), explore qué hacen las siguientes funciones: length(), sort(), rev() y unique().
Ahora que aprendimos cómo generar un vector, veremos cómo se evalúan las expresiones lógicas en este contexto. Por ejemplo:
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:
Obviamente, los operadores relaciones también son válidos:
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:
También es posible indicar más de un elemento a la izquierda del operador:
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
En cambio, con solo haber un sólo elemento igual a FALSE, la función all() devuelve FALSE:
La función any(), devuelve TRUE si al menos un elemento del vector lógico es TRUE:
Caso contrario, si todos los elementos son iguales a FALSE, any() devuelve 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:
Si sumamos los elementos del vector lógico, obtenemos lo siguiente:
¿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).
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:
[1] -1.5
[1] -5.00 -4.00 -2.75
[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 -:
[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.
[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
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:
[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:
[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:
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:
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().
En el contexto de valores NA, es útil la función na.omit(), que remueve todos los elementos que sean NA:
[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:
[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:
[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.
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:
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.
rep() y seq() para generar los siguientes vectores:character, que indique 4 categorías discretas, repetidas de a 3 cada una.c(F, T, F, T).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: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%.