Clases, modos y filtros en R

Formato y estructura de los diferentes objetos de datos en R - Filtrar y seleccionar elementos de los objectos de R

1 Objetos de datos en R

1.1 Clases simples: vectores y matrices

Existen varios tipos de objetos en R. Dentro de los más simples están

1.1.1 vector

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:

names(numeros)<-c("a","b","c")
numeros
a b c 
3 1 6 

1.1.2 Arrays y Matrices

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.

dim(matExample)
[1] 4 3
nrow(matExample)
[1] 4
ncol(matExample)
[1] 3

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"

1.2 Los modos de datos

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:

mode(numeros)
[1] "numeric"
mode(matExample)
[1] "character"

1.2.1 Modo logico

El modo más simple y más ligero es el modo de logica booleana logical, puede contener los valores TRUE y FALSE

(vecLog <- c(T,F,F,T,T))
[1]  TRUE FALSE FALSE  TRUE  TRUE
mode(vecLog)
[1] "logical"

1.2.2 Modo numerico

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

1.2.3 Modo caracter

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…

1.2.4 Modo factor

Finalmente existe el modo factor, para almacenar variables con un numero de posibilidades de valores limitado.

(factorExample <- factor(c("Sí","No","Sí","Tal vez"),levels=c("Sí","No","Tal vez")))
[1] Sí      No      Sí      Tal vez
Levels: Sí No Tal vez
mode(factorExample)
[1] "numeric"

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

1.3 Clases compuestas: list y data.frame

1.3.1 Un solo modo en los vectores y matrices

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).

1.3.2 Las listas

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"

1.3.3 Los data frames

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

1.4 Recapitulativo de las clases de los objetos en R

Table 1: Tipos principales de objetos, y sus caracteristicas heredadas. La columna modo unico indica si el objeto solo puede contenir datos de un modo (ver noción de atomic mode).
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:

length(matExample)
[1] 12
nrow(matExample)
[1] 4

Un data.frame hereda las caracteristicas de los list. Además, hereda las características de los arrays!


2 Applicar filtros a los objetos

Para filtrar objetos en R, se utilizan los operadores de tipo [...]. Esos operadores aceptan 3 tipos de filtros:

2.1 Filtros sobre vectores

2.1.1 Modo logical

numeros
a b c 
3 1 6 
numeros[c(T,F,T)]
a c 
3 6 

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

2.1.1.1 Operadores logicos

Varios operadores permiten obtener vectores logicos, por ejemplo:

Así, 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 

2.1.2 Indices

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 

2.1.3 Nombres

numeros[c("a","c")]
a c 
3 6 

2.1.4 Filtros de vectores heredados

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.

2.2 Filtros sobre arrays

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.

2.3 Filtros sobre list

Para las list existen operadores particulares: $ y [[...]]

2.3.1 El operador $

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"

2.3.2 El operador [[...]]

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

2.3.3 Los data.frame son listas

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

2.4 Cambiar los contenidos filtrados

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