<- c(3, 5, 9) a
8 ESTRUCTURAS DE DATOS
R es un lenguaje con características compatibles con la programación orientada a objetos. Un objeto es una entidad sobre la cual puede operarse. Así, un número es un objeto, también son objetos una cadena de caracteres, una fórmula o un resultado.
Aunque es evidente la posibilidad de operar sobre un número, no lo es tanto la posibilidad de operar sobre una cadena de caracteres, sobre una fórmula o sobre un resultado. No obstante, si se considera, por ejemplo, la función print
, tomando tales objetos como argumento para mostrarlos en la consola, la posibilidad de operar sobre los mismos se hace clara1.
Un grupo de objetos de gran interés es el de los que actúan como contenedores de información, permitiendo agruparla o estructurarla.
La estructura más básica es el vector, el cual está definido como un conjunto unidimensional de elementos del mismo tipo (todos enteros, todos reales, todos complejos, todos caracteres, todos lógicos o todos en bruto).
En orden de complejidad, sigue la matriz, definida como una estructura bidimensional de elementos del mismo tipo.
Está también el arreglo, que constituye la generalización de la matriz, pudiendo tener más de dos dimensiones; la matriz sería un arreglo particular de dos dimensiones.
El data frame, al igual que la matriz, es una estructura bidimensional, pero es más general que esta, pues admite elementos de diferentes tipos. Esta es la manera en la que suelen estructurarse datos de diferente tipo (entero, real, carácter, complejo, lógico, bruto). El data frame es la base de datos por excelencia en R.
La lista es la estructura más general, teniendo la posibilidad de contener no solo vectores de diferente tipo, sino también cualquiera de las otras estructuras, incluyendo otras listas.
Los vectores, las matrices y los arreglos están restringidos a contener elementos de un único tipo. A tales estructuras se les denomina atómicas.
Los data frames y las listas son estructuras que admiten elementos de diferentes tipos. A tales estructuras se les denomina recursivas.
Las estructuras contenedoras de datos en R, en orden de complejidad son:
- Vector
- Matriz
- Arreglo
- Data frame
- Lista
Las tres primeras son estructuras atómicas; las dos últimas, recursivas.
8.1 Vectores
La manera más común de crear un vector es mediante el uso de la función de concatenación c
y el operador de asignación <-
, separando los diferentes elementos con comas.
Para crear, por ejemplo, un vector llamado a
, que contenga los elementos 3, 5 y 9, se usa la siguiente instrucción:
En la anterior expresión, la función c
es la que define el vector (nemotécnicamente, puede recordarse como combinar); c(3, 5, 9)
es un vector.
El paso correspondiente al almacenamiento de dicho objeto en el ambiente de trabajo, es decir, la asignación, se requeriría únicamente si se quisiera usar dicho vector en un proceso posterior.
Si no se realizara el paso de asignación, se generaría un vector que a pesar de su existencia efímera podría bastar para un propósito dado, como servir de argumento en una función determinada.
La siguiente instrucción crea un vector tipo carácter. Al definir este tipo de vectores, es necesario entrecomillar cada uno de los elementos constituyentes, siendo posible usar comillas dobles o sencillas.
<- c("Gabriela", 'Carlina', "Luz", 'Marina') nombres
Para verificar si un objeto es un vector se usa la función is.vector(objeto)
, la cual genera un resultado lógico (falso o verdadero).
En la sección 10.4 se discuten algunas salvedades.
8.2 Matrices
Las matrices son estructuras bidimensionales (filas y columnas) que agrupan objetos del mismo tipo.
Supóngase que se quiere crear una matriz numérica con dos filas y tres columnas, para alojar la siguiente información:
2 | 0 | 5 |
-1 | 9 | 1 |
Para tal efecto, se usa la siguiente instrucción.
matrix(c(2, 0, 5, -1, 9, 1), nrow = 2, ncol = 3, byrow = TRUE)
matrix
es la función que define la creación de la matriz. Su primer argumento es un vector con la información que se distribuirá en filas y columnas. Los argumentos nrow
y ncol
especifican el número de filas y de columnas respectivamente.
El cuarto argumento de la función matrix
especifica la manera en la que se distribuyen los elementos. Su valor por defecto es byrow = FALSE
.
Por tanto, si dicho argumento fuera omitido (o se definiera explícitamente como byrow = F
), los elementos ingresados se ordenarían por columnas.
Así, si se hubiera omitido este argumento en la instrucción anterior —en lugar de la matriz objetivo— se obtendría la siguiente matriz:
[,1] [,2] [,3]
[1,] 2 5 9
[2,] 0 -1 1
Considérense nuevamente los siguientes elementos, con base en los cuales se quiere definir una matriz con dos filas y tres columnas:
2 | 0 | 5 |
-1 | 9 | 1 |
Considérense ahora los vectores a
, b
y c
, definidos con base en las columnas de la matriz objetivo:
<- c(2, -1)
a <- c(0, 9)
b <- c(5, 1) c
Podría pensarse en concatenar dichos vectores para obtener la matriz objetivo, así:
c(a, b, c)
[1] 2 -1 0 9 5 1
Se observa que, en lugar de la matriz objetivo, se obtiene un vector. Esto es debido a que la función c
siempre da lugar a vectores.
Existen, sin embargo, un par de funciones de concatenación que sí dan lugar a matrices:
rbind
, que permite combinar vectores por filas (rows)cbind
, que permite concatenar vectores por columnas (columns)
Para crear la matriz objetivo a partir de los vectores a
, b
y c
definidos anteriormente, se usaría cbind
:
<- cbind(a, b, c) m1
Para ver la matriz resultante en consola, se usa la función print
:
print(m1)
a b c
[1,] 2 0 5
[2,] -1 9 1
La concatenación por filas sería así:
<- c(2, 0, 5)
a <- c(-1, 9, 1) b
<- rbind(a, b)
m2 print(m2)
[,1] [,2] [,3]
a 2 0 5
b -1 9 1
Para verificar si un objeto es una matriz se usa la función is.matrix(objeto)
, la cual genera un resultado lógico (falso o verdadero).
is.matrix(m2)
[1] TRUE
8.2.1 Álgebra matricial
Las matrices en R no son solo contenedores de información, sino que comparten las características de las matrices como concepto matemático. Esto hace posible su participación en operaciones de álgebra matricial.
Si usted está iniciándose con R, tratando de entender su estructura básica, y de momento no está interesado en su uso como herramienta de álgebra matricial, le recomedamos que se salte esta sección y pase directamente a la sección 8.3.
Sin embargo, no olvide que esta sección está aquí… Podría serle muy útil a futuro.
8.3 Arreglos
Cuando se tienen más de dos dimensiones con elementos del mismo tipo, es posible estructurar la información en arreglos. Considérese una situación hipotética en la que se evalúan tres variables sobre cuatro unidades muestrales, en dos tiempos, pudiendo obtenerse como resultado cualquiera de las letras del alfabeto.
Tiempo1 | |||
v1 | v2 | v3 | |
unidad1 | a | x | d |
unidad2 | c | m | b |
unidad3 | f | j | u |
unidad4 | d | l | y |
Tiempo2 | |||
v1 | v2 | v3 | |
unidad1 | b | h | r |
unidad2 | j | o | s |
unidad3 | h | w | n |
unidad4 | l | p | q |
La anterior información podría estructurase en un arreglo de tres dimensiones, con las unidades en la primera dimensión, las variables en la segunda y el tiempo en la tercera, lo cual puede visualizarse como un cubo, en el que las tres dimensiones representan altura, ancho y profundidad, respectivamente.
Aunque la analogía entre un cubo y un arreglo de tres dimensiones puede facilitar el entendimiento del arreglo, la inexistencia de este tipo de relaciones en arreglos con mayor número de dimensiones no impide la existencia de estos. Si se tuviera otro factor, como localidad, por ejemplo, podría incorporarse en la cuarta dimensión. De igual manera, podrían generarse dimensiones adicionales.
Aunque podría usarse una única instrucción para construir el arreglo en cuestión, se ilustrará en dos pasos, con el fin de hacer más claro el proceso.
Inicialmente, se construye un vector de 24 elementos con toda la información.
<- c('a', 'c', 'f', 'd', 'x', 'm', 'j', 'l',
vector 'd', 'b', 'u', 'y', 'b', 'j', 'h', 'i',
'h', 'o', 'w', 'p', 'r', 's', 'n', 'q')
A continuación, se genera el arreglo:
<- array(vector, dim = c(4, 3, 2)) letras
La función array
concatena los objetos contenidos en vector
, por columnas (no existe la opción para concatenar por filas). El valor del argumento dim
debe ser un vector de enteros con la longitud de cada una de las dimensiones.
Para verificar si un objeto es un arreglo, se utiliza la función is.array(objeto)
.
is.array(letras)
[1] TRUE
Todas las matrices son a su vez arreglos; sin embargo, solo los arreglos de dos dimensiones son matrices.
8.4 Data frames
El data frame es una estructura rectangular (dos dimensiones), que puede estar conformada por objetos de diferente tipo en cada columna (pero del mismo tipo dentro de cada columna). Es decir que se trata de una estructura recursiva.
Esto contrasta con las estructuras atómicas ilustradas en las secciones anteriores (vectores, matrices y arreglos), que exigen que todos los elementos sean del mismo tipo (cf. nota 8.1).
Para verificar si un objeto es atómico, se usa la función is.atomic(objeto)
.
is.atomic(letras)
[1] TRUE
Considérense los siguientes vectores:
1<- c("a23", "f31", "j33", "m54")
id 2<- c(2.4, 7.9, 1.1, 8.5)
v1 3<- c(4+3i, 2-0.8i, 1+1.1i, 3-5i) v2
- 1
- Vector de caracteres
- 2
- Vector numérico
- 3
- Vector complejo
Una manera de generar un data frame es a través de la agregación de vectores, sin importar que estos sean de diferente tipo. La siguiente instrucción genera un data frame concatenando por columnas los vectores definidos anteriormente.
<- data.frame(id, v1, v2)
df print(df)
id v1 v2
1 a23 2.4 4+3.0i
2 f31 7.9 2-0.8i
3 j33 1.1 1+1.1i
4 m54 8.5 3-5.0i
Esta capacidad de combinar objetos de diferentes tipos hace del data frame la estructura ideal para alojar bases de datos en R. Los data frames se organizan con las observaciones o individuos en filas, y variables en columnas.
No es necesario que los objetos que se concatenan para conformar un data frame sean vectores; también pueden concatenarse matrices, arreglos u otros data frames, exigiéndose únicamente que todos tengan el mismo número de filas.
Puesto que el data frame es una estructura bidimensional, al incluir un arreglo en la definición de un data frame, este se “aplana” a dos dimensiones.
Así, por ejemplo, el arreglo letras
generado en la sección 8.3 generaría un data frame de cuatro filas (las 4 unidades muestrales, que están en la primera dimensión) y seis columnas en las que aparecen concatenadas las 3 variables de cada uno de los 2 tiempo: primero las 3 variables del tiempo 1 y a continuación las 3 variables del tiempo 2.
<- data.frame(letras)
df2 print(df2)
X1 X2 X3 X4 X5 X6
1 a x d b h r
2 c m b j o s
3 f j u h w n
4 d l y i p q
Cuando se usan las funciones read.table
, read.delim
, read.delim2
, read.csv
, read.csv2
o read_excel
(cf. capítulo 6), los objetos que se generan son data frames.
Para verificar si un objeto es un data frame se usa la función is.data.frame (objeto)
, la cual genera un resultado lógico (falso o verdadero).
is.data.frame(df2)
[1] TRUE
8.5 Listas
La lista constituye la estructura más flexible, pudiendo estar conformada por objetos de cualquier tipo y clase, incluso por otras listas.
Dada la diversidad de objetos que pueden conformar una lista, en estas no existe el concepto de filas, columnas ni de ninguna otra dimensión. Las listas son objetos unidimensionales.
Puesto que las listas son objetos unidimensionales, en ocasiones se hace referencia a las mismas como vectores genéricos, es decir, vectores que pueden contener elementos de distintos tipos, a diferencia de los vectores básicos definidos en la sección 8.1, que están restringidos a contener objetos de un único tipo.
A los vectores básicos se les denomina vectores atómicos cuando se desea diferenciarlos de las listas.
La figura 8.1 ilustra el concepto de las listas como vectores genéricos. La figura 8.1 (a) representa dos vectores, cada uno de los cuales está restringido a contener elementos de un mismo tipo, los cuales se ubican a lo largo de una única dimensión. La figura 8.1 (b) representa una lista, la cual, a pesar de manejar también una única dimensión, puede contener elementos de cualquier tipo.


Considérense los siguientes objetos de diferente naturaleza:
1<- c('Iván', 'Rosa', 'Diana')
nombre 2<- c(34, 43)
edad 3<- c(TRUE, TRUE, FALSE)
aprobado 4<- matrix(c(2, 0, 5, -1, 9, 1), nrow = 2, ncol = 3) score
- 1
- Vector de caracteres
- 2
- Vector numérico
- 3
- Vector lógico
- 4
- Matriz numérica
Los anteriores objetos pueden concatenarse en una lista, así:
<- list(nombre, edad, aprobado, score) lista1
La lista es el contenedor más general, pudiendo contener incluso otras listas. Para ilustrarlo, generaremos una nueva lista, usando lista1
y el arreglo letras
presentado en la sección 8.3:
<- list(letras, lista1) lista2
Para verificar si un objeto es una lista se usa la función is.list(objeto)
, la cual genera un resultado lógico (falso o verdadero).
is.list(lista2)
[1] TRUE
Asimismo, puede verificarse que las listas también son vectores (vectores genéricos):
is.vector(lista2)
[1] TRUE
El lenguaje R proporciona una variada gama de contenedores que resulta suficiente para satisfacer las necesidades de organización de la información.
El vector constituye la manera más básica de agrupar datos; es el objeto más utilizado para la definición de argumentos secundarios en las funciones de R; es la estructura que se utilizaría siempre que los datos fueran del mismo tipo y no exigieran un arreglo multidimensional.
Cuando se requiera realizar operaciones matriciales, los objetos deben ser matrices (o eventualmente vectores; cf. sección 8.2.1).
El arreglo resulta útil para organizar datos del mismo tipo en más de dos dimensiones.
El data frame es la estructura en la que se organizan las bases de datos en R. La mayoría de los procedimientos estadísticos implementados en R exigen que el objeto de entrada sea un data frame. Cuando se importan datos, se genera un data frame.
La lista resulta útil cuando se requiere tener información de diversa índole (tamaño, dimensionalidad, tipo…) en un mismo contenedor. Este es el objeto que suele usarse para alojar los resultados de las funciones.
El anterior resumen deja claro que casi todas las estructuras contenedoras de datos tienen un nicho muy definido… excepto los arreglos, que no son muy comunes y cuyas posibilidades de uso no quedan muy claras.
Si está interesado en ver una aplicación práctica de un arreglo como contenedor tetradimensional, puede explorarla a continuación. No obstante, si usted viene estudiando este libro en orden, le sugerimos posponer esta revisión para después de haber estudiado la sección 13 (indexación), la sección 9.4 (reciclaje de elementos), el capítulo 18 (funciones por grupos) y la sección 20.1 (ciclos).
Referencias Bibliográficas
La función
print
se presenta en el capítulo 14↩︎