Formato y estructura de los diferentes objetos de datos en R - Filtrar y seleccionar elementos de los objectos de R
Existen varios tipos de objetos en R. Dentro de los más simples están
Una noción central para entender el funcionamiento de R es el vector.
Un vector es un ensamblaje de valores, y casi todos los objetos de R son vectores.
La forma más simple de crear un vector es la función c:
(numeros <- c(3,1,6))
[1] 3 1 6
Un vector es un objeto de una dimensión, que tiene una longitud.
length(numeros)
[1] 3
Los elementos de los vectores pueden tener nombres:
Existen también objetos que tienen más de una dimensión, en R usualmente pertenecen a la familia de los arrays.
El objeto de la clase array más simple es la matriz, que se puede crear con la función matrix.
(matExample <- matrix(letters[1:12],nrow=4,ncol=3))
[,1] [,2] [,3]
[1,] "a" "e" "i"
[2,] "b" "f" "j"
[3,] "c" "g" "k"
[4,] "d" "h" "l"
Los arrays tienen dimensiones. Acá vamos a trabajar con arrays de 2 dimensiones pero existen arrays de más de 2 dimensiones.
Los arrays pueden tambien tener nombres de filas y nombres de columnas
colnames(matExample)<-c("A","B","C")
rownames(matExample)<-c("fila1","fila2","fila3","fila4")
matExample
A B C
fila1 "a" "e" "i"
fila2 "b" "f" "j"
fila3 "c" "g" "k"
fila4 "d" "h" "l"
En R existen varios modos que corresponden a varios tipos de datos que se pueden manejar, y que se almacenan de manera diferente en la memoria del computador. Por ejemplo, los objetos numeros y matExample tienen modos diferentes:
El modo más simple y más ligero es el modo de logica booleana logical, puede contener los valores TRUE y FALSE
Existen los modos numéricos, así como en el objeto numeros. Los objetos de modo numérico tienen varías precisiones y forma de almacenamiento. Los más importantes para conocer son los números enteros (integer) y los números generales (numeric que pueden ser de tipos single precision y double precision).
(numInt <- c(5L,3L,1L))
[1] 5 3 1
is.integer(numInt)
[1] TRUE
(numOtros <- c(8.1837, 6.94785, 5, 17/9))
[1] 8.183700 6.947850 5.000000 1.888889
is.integer(numOtros)
[1] FALSE
Luego podemos mencionar los objetos de modo “character”, como en la matriz matExample. Los objetos de tipo character pueden almacenar cadenas de caracter con varías letras y simbolos alphanumericos:
(vecCar <- c("palabras","con espacio", "o numeros 123", "o otras cosa [^"))
[1] "palabras" "con espacio" "o numeros 123"
[4] "o otras cosa [^"
mode(vecCar)
[1] "character"
nchar(vecCar)
[1] 8 11 13 15
Anotar: el modo caracter es el modo más pesado para la memoria en R. Si tienen problemas de memoria limitada en un script es mejor evitarlos…
Finalmente existe el modo factor, para almacenar variables con un numero de posibilidades de valores limitado.
Anotar: R almacena los factores como numéricos en memoria:
as.numeric(factorExample)
[1] 1 2 1 3
Permite economizar mucho espacio en memoria, pero también puede ser la raíz de errores difíciles de detectar en un código, cuidado!
NB: para que lo sepan, existen otros modos como los números complejos, pero son poco útiles en la gestión de datos de biodiversidad
Los vectores y matrices solo pueden contener datos de un modo:
(vecTestMode <- c(T, 1L, 4.14, "palabra"))
[1] "TRUE" "1" "4.14" "palabra"
mode(vecTestMode)
[1] "character"
Anotar: lo que pasó con este vector es que todo se volvió character porque este modo puede integrar los demás (logical < factor < numeric < character).
Existen una clase de objetos que pueden mezclar diferentes modos: la clase list. Una list es un vector de otros objetos.
Se puede crear con la función list
(list1 <- list(numeros, matExample))
[[1]]
a b c
3 1 6
[[2]]
A B C
fila1 "a" "e" "i"
fila2 "b" "f" "j"
fila3 "c" "g" "k"
fila4 "d" "h" "l"
Se pueden también poner nombres a los sub-objetos de la list en la creación del objeto:
(list1_withNames <- list(numeros=numeros, `Un ejemplo de matriz`=matExample))
$numeros
a b c
3 1 6
$`Un ejemplo de matriz`
A B C
fila1 "a" "e" "i"
fila2 "b" "f" "j"
fila3 "c" "g" "k"
fila4 "d" "h" "l"
Existe un caso particular de list: el data.frame. Es una list de vectors que tienen todos la misma longitud. Dado que es una list, cada uno de los vectores puede tener un modo diferente. También es un array: es decir que los vectors, que tienen todos la misma longitud, representan las columnas de una tabla.
(DF_example <- data.frame(
country=c("Chile","Colombia","Francia"),
surAmerica=c(T,T,F),
superficie_km2=c(756626,1142000,549134)
))
country surAmerica superficie_km2
1 Chile TRUE 756626
2 Colombia TRUE 1142000
3 Francia FALSE 549134
| vector | array | modo.único | list | |
|---|---|---|---|---|
| vector | TRUE | FALSE | TRUE | FALSE |
| matriz | TRUE | TRUE | TRUE | FALSE |
| list | TRUE | FALSE | FALSE | TRUE |
| data.frame | FALSE | TRUE | FALSE | TRUE |
La tabla 1 contiene las características principales de las clases de objetos principales en R (anotar: existen otras clases de objetos, pero esas son las clases de objetos más comunes para almacenar datos).
Para los que quieren ir más allá en la comprensión de la tabla 1: el lenguaje de programación R es un lenguaje de programación orientado a objeto. Eso implica que el tratamiento del objeto en el lenguaje va a depender de características que cada objeto va a heredar de familias de objetos que se llaman clases (classes). Por ejemplo, los objetos matrix en R heredan las características de las clases vector y array. Basicamente, una matrix es un vector que tiene dos dimensiones (filas y columnas). Por esa razon, tiene una longitud, como todos los vectores, pero tambien un numero de filas y un numero de columnas, como todos los arrays:
Un data.frame hereda las caracteristicas de los list. Además, hereda las características de los arrays!
Para filtrar objetos en R, se utilizan los operadores de tipo [...].
Esos operadores aceptan 3 tipos de filtros:
Si el vector utilizado en el filtro tiene una longitud inferior al vector que queremos filtrar, los valores están repetidos hasta obtener la longitud final
factorExample
[1] Sí No Sí Tal vez
Levels: Sí No Tal vez
factorExample[c(F, T)]
[1] No Tal vez
Levels: Sí No Tal vez
Por ejemplo, para conocer todos los múltiples de 3 entre 1 y 100:
(mul3 <- (1:100)[c(F, F, T)])
[1] 3 6 9 12 15 18 21 24 27 30 33 36 39 42 45 48 51 54 57 60 63 66
[23] 69 72 75 78 81 84 87 90 93 96 99
Varios operadores permiten obtener vectores logicos, por ejemplo:
==: es igual a!=: es diferente de>, >=: es superior a, es superior o igual a>, >=: es inferior a, es inferior o igual a& : operador booleano y|: operador booleano o!: operador booleano noAsí, todos esos operadores se pueden utilizar en los filtros logicos:
numeros >= 2
a b c
TRUE FALSE TRUE
numeros[numeros >= 2]
a c
3 6
numeros[numeros >= 2 & numeros != 6]
a
3
numeros[!(numeros >= 2 & numeros != 6)]
b c
1 6
numeros[2:3]
b c
1 6
Permite cambiar el orden de los vectores:
numeros[length(numeros):1]
c b a
6 1 3
Podemos tambien repetir elementos
numeros[c(1:3,2)]
a b c b
3 1 6 1
numeros[c("a","c")]
a c
3 6
Vimos antes que una matriz es un “vector con dimensiones”, así que los filtros de vectores se pueden aplicar:
matExample
A B C
fila1 "a" "e" "i"
fila2 "b" "f" "j"
fila3 "c" "g" "k"
fila4 "d" "h" "l"
matExample[c(T,T,F,T)]
[1] "a" "b" "d" "e" "f" "h" "i" "j" "l"
Anotar: el orden del vector incluido en la matriz es por columna, así que lo que hicímos con este filtro es buscar el vector de valores que excluye la fila 3.
Tambien vimos que las list son vectores de objetos, los filtros de vectores funcionan tambien sobre esos objetos:
list1_withNames["numeros"]
$numeros
a b c
3 1 6
Anotar también que las filas o las columnas de un array son vectores, entonces se pueden aplicar los filtros de vectores sobre la extracción de columnas y filas de array, como los data.frame.
En los casos de los arrays, se pueden aplicar filtros sobre filas y columnas. También funcionan con el operador [...], solo se separan por una coma:
matExample
A B C
fila1 "a" "e" "i"
fila2 "b" "f" "j"
fila3 "c" "g" "k"
fila4 "d" "h" "l"
matExample[2:3,c(T,F,T)]
A C
fila2 "b" "j"
fila3 "c" "k"
Cuando se utiliza la coma, pero el filtro de columna o fila es vacío entonces corresponde a guardar todos los elementos de la dimensión sin filtro:
DF_example
country surAmerica superficie_km2
1 Chile TRUE 756626
2 Colombia TRUE 1142000
3 Francia FALSE 549134
DF_example[,"surAmerica"]
[1] TRUE TRUE FALSE
DF_example[DF_example[,"surAmerica"],]
country surAmerica superficie_km2
1 Chile TRUE 756626
2 Colombia TRUE 1142000
En este ejemplo utilizamos un filtro logico extraído de la columna surAmerica para aplicarlo sobre las filas de la tabla misma.
Para las list existen operadores particulares: $ y [[...]]
$El operador $ permite extraer un elemento de la list con su nombre:
list1_withNames$numeros
a b c
3 1 6
Cuando los nombres de los elementos tienen espacios o caracteres particulares, el operador se puede utilizar con el caracter `
list1_withNames$`Un ejemplo de matriz`
A B C
fila1 "a" "e" "i"
fila2 "b" "f" "j"
fila3 "c" "g" "k"
fila4 "d" "h" "l"
[[...]]Otra forma de extraer un elemento de una list es utilizar el operador [[...]].
list1_withNames[[1]]
a b c
3 1 6
list1_withNames[["Un ejemplo de matriz"]]
A B C
fila1 "a" "e" "i"
fila2 "b" "f" "j"
fila3 "c" "g" "k"
fila4 "d" "h" "l"
Anotar: la diferencia entre [...] y [[...]] es que la primera solución envía una lista, y la segunda envia el contenido del elemento.
list1_withNames[1]
$numeros
a b c
3 1 6
is.list(list1_withNames[1])
[1] TRUE
list1_withNames[[1]]
a b c
3 1 6
is.list(list1_withNames[[1]])
[1] FALSE
No olvidar que los data.frames heredan las caracteristicas de las list:
DF_example[["country"]]
[1] "Chile" "Colombia" "Francia"
DF_example[DF_example$surAmerica,]$superficie_km2
[1] 756626 1142000
Todos los filtros que vimos en este documento pueden permitir afectar nuevos valores a los elementos filtrados:
numeros
a b c
3 1 6
numeros["b"] <- 12
numeros
a b c
3 12 6