5 Más sobre los objetos en R
R es un lenguaje de programación orientado a la creación de objetos14. Los objetos son cualquier cosa a la que pueda asignársele una variable, además permiten que el usuario almacene la información que necesita para llevar a cabo su proyecto.
En el capítulo anterior creamos diferentes objetos: unos que contenían un solo número; otros que contenían resultados lógicos (TRUE o FALSE); otros que estaban compuestos por varios números, y otros que eran colecciones de texto.
En este capítulo estudiaremos algunos tipos de objetos importantes para continuar con nuestra introducción a R.
Los tipos de objetos en R se conocen en la comunidad como clases. Existen muchas clases de objetos, pero las clases más sencillas son 5:
- numeric: números reales o decimales
- integer: números enteros
- complex: números complejos
- character: carácteres
- logical: resultados lógicos (TRUE o FALSE)
Como lo vimos en el Capítulo 4, los objetos pueden combinarse para crear otros nuevos. Es más, hay objetos que tienen otros objetos que los conforman y cada uno puede ser de diferente clase. Así también tendremos otras clases para objetos compuestos, por ejemplo,
- list: listas
- matrix: matriz
- array: colección de objetos
- data.frame: base de datos
En este capítulo discutiremos estas clases de objetos.
5.1 Clases sencillas de objetos
Los objetos más sencillos pueden ser los de la clase numeric que se emplea para números reales o decimales. Estos son tratados como variables continuas. La clase integer corresponde a un número entero (sin decimales). En este caso R trata a estos objetos como variables discretas. La clase complex corresponde a aquellos que contienen un número complejo. La clase logical se refiere a objetos que toman valores FALSE (falso) o TRUE (verdadero). Y la clase character se emplea para almacenar texto, conocido como cadenas de carácteres en R. La forma más sencilla de almacenar datos (de texto) bajo el formato de carácteres es utilizando comillas alrededor del fragmento de texto.
En el capítulo anterior (Capítulo 4) creamos 11 objetos. A continuación, carga el workspace o corre de nuevo el script del capítulo anterior. Un workspace previamente guardado (archivo con la extensión .RData
) puede cargarse de las siguiente forma:
- Hacer clic en el icono de un folder con flecha saliente (ver Figura 5.1) en la parte superior de la pestaña
Enviroment
del panel en la parte superior derecha.
- Emplear el menú de “Session”. Puedes hacer clic en
Session | Load Workspace...
. - Emplear código. Puedes emplear la función load(), cuyo único argumento es el nombre del archivo (entre comillas) con el que grabaste el archivo
.RData
y su ruta si se requiere. Recuerda que R buscará cualquier archivo en el working directory, a menos que se especifique lo contrario; por ejemplo
load(file = "res_cap4.RData")
Ahora que ya tienes el mismo workspace que empleamos en el Capítulo 4, comprobemos los objetos que tenemos empleando la función objets() que vimos en el capítulo anterior.
objects()
## [1] "modified_plot" "nombres" "nombres2"
## [4] "regular_plot" "source" "v2"
## [7] "v3" "ventas_1" "w"
## [10] "x" "x1" "x2"
## [13] "y" "z"
Para conocer la clase de cada objeto podemos emplear la función class() , por ejemplo
class(nombres)
## [1] "character"
Puedes emplear esta función para comprobar la clase de todos los 11 objetos como se reporta en el Cuadro @\(\ref{tab:Class}\)
Objeto | Clase | Objeto | Clase |
---|---|---|---|
nombres | character | x | numeric |
nombres2 | rclass(nombres2) |
x1 | rclass(x1) |
v2 | rclass(v2) |
x2 | rclass(x2) |
v3 | rclass(v3) |
y | rclass(y) |
ventas_1 | rclass(ventas_1) |
z | rclass(z) |
w | rclass(w) |
Ya creamos objetos de todas las clases, menos de la clase complex. No es común emplear este tipo de objetos, pero si alguna vez necesitaras crear uno con un número complejo, es muy sencillo; por ejemplo:
# asingamos al objeto r el número complejo 1+2i
<- 1 + 2i
r r
## [1] 1+2i
# miramos la clase de este objeto
class(r)
## [1] "complex"
Antes de hablar de los objetos compuestos, es importante mencionar que es posible cambiar la clase de un objeto empleando funciones. Las funciones que podemos emplear para cambiar cualquier objeto (siempre y cuando tenga sentido) a las cinco clases simples estudiadas son: as.numeric(), as.integer(), as.carachter(), as.logical() y as.complex(). Estas funciones sólo necesitan como argumento un objeto. Por ejemplo, podemos pasar el objeto de clase numeric a clase character de la siguiente manera:
# cambiamos la clase del objeto y de numeric a character
<- as.character(y)
y # miramos la clase de este objeto
class(y)
## [1] "character"
# regresemos el objeto a su clase original
<- as.numeric(y)
y class(y)
## [1] "numeric"
Existe otra clase de objeto simple que es útil cuando trabajamos con información cualitativa: la clase factor . Esta clase se emplea para registrar datos cualitativos, como el sexo, los colores y si se está defectuoso o no. Esta se diferencia de la clase character en que puede tomar un número limitado de opciones (niveles o levels en inglés).
Continuemos con el ejemplo con el que empezamos en el capítulo anterior (Capítulo 4); en este registramos las compras en millones de pesos durante el primer año de operación de la compañía de 4 clientes en el objeto ventas_1
y cuyos nombres guardamos en el objeto nombres
. Ahora creemos el objeto sexo
en el que registraremos el sexo (femenino o masculino) de cada uno de los clientes.
# recordando los nombres
nombres
## [1] "Juliana" "Matías" "Mariana" "Luís"
# creamos el objeto sexo
<- factor(c("Femenino", "Masculino", "Femenino",
sexo "Masculino"))
# constatamos la clase
class(sexo)
## [1] "factor"
También podemos constatar cuales son los niveles de un objeto factor empleando la función levels().
# constatamos los niveles del objeto de clase factor
levels(sexo)
## [1] "Femenino" "Masculino"
Observa que los objetos sencillos que hemos tratado hasta hora pueden ser de un solo dato (como el objeto x1
) o pueden tener varios (como el objeto ventas_1
). Los objetos como ventas_1
y v2
son conjuntos unidimensionales de datos cuyos elementos son numéricos, y por tanto, el objeto como tal es de clase numeric numérico. A este tipo de objetos se les conoce como vectores, estos son objetos que contienen conjuntos unidimensionales de datos (solo una fila), los cuales pueden ser de clase integer, complex, character, logical o fator. En todo caso, todos los elementos dentro del vector deben ser de la misma clase.
5.2 Clases de objetos compuestos
Hay objetos que son composiciones de otros y generan nuevas clases de objetos como la clase list. El objecto de esta clase es una estructura de datos que contiene elementos de diferentes tipos como integer, complex, character, logical, o fator. En R la lista puede ser creada usando la función list(); por ejemplo, podemos crear el objeto l1
que tenga los objetos w
, x
y nombres2
:
# creamos el objeto l1 de clase lista
<- list(w, x, nombres2)
l1 l1
## [[1]]
## [1] FALSE
##
## [[2]]
## [1] 1
##
## [[3]]
## [1] "x_1" "y_1" "x_2" "y_2" "x_3" "y_3" "x_4" "y_4"
## [9] "x_5" "y_5" "x_6" "y_6" "x_7" "y_7" "x_8" "y_8"
## [17] "x_9" "y_9" "x_10" "y_10"
# miramos la clase de este objeto
class(l1)
## [1] "list"
Este tipo de objetos tendrán diferentes compartimientos (slots), uno para cada objeto que conforma la lista. A los slots se puede acceder empleando los corchetes cuadrados ([]
) para determinar el número del slot al que se quiere acceder; por ejemplo, en nuestro objeto l1
tenemos tres slots. Accedamos al tercer slot:
# consultando el tercer slot del objeto l1
3] l1[
## [[1]]
## [1] "x_1" "y_1" "x_2" "y_2" "x_3" "y_3" "x_4" "y_4"
## [9] "x_5" "y_5" "x_6" "y_6" "x_7" "y_7" "x_8" "y_8"
## [17] "x_9" "y_9" "x_10" "y_10"
También podemos ponerle nombres a los slots; por ejemplo,
# poniéndole el nombre a los slots del objeto l1
names(l1) <- c("objeto_w", "objeto_x", "objeto_nombres")
l1
## $objeto_w
## [1] FALSE
##
## $objeto_x
## [1] 1
##
## $objeto_nombres
## [1] "x_1" "y_1" "x_2" "y_2" "x_3" "y_3" "x_4" "y_4"
## [9] "x_5" "y_5" "x_6" "y_6" "x_7" "y_7" "x_8" "y_8"
## [17] "x_9" "y_9" "x_10" "y_10"
Al ponerle nombre a los slots, podemos acceder a cada slot por su nombre empleando el signo $
entre el nombre del objeto y el slot; por ejemplo,
# consultando los slots del objeto l1 por sus nombres
$objeto_w
l1$objeto_nombres l1
## [1] FALSE
## [1] "x_1" "y_1" "x_2" "y_2" "x_3" "y_3" "x_4" "y_4"
## [9] "x_5" "y_5" "x_6" "y_6" "x_7" "y_7" "x_8" "y_8"
## [17] "x_9" "y_9" "x_10" "y_10"
Otra clase de objeto compuesto muy común es matrix (matriz). Una matriz en R es un conjunto de 2 dimensiones (filas y columnas) en los que cada elemento tiene la misma clase. Los objetos de clase matrix se pueden crear con la función matrix() , cuyos argumentos son:
Donde:
- data: son los datos que serán incluidos en la matriz.
- nrow: número de filas de la matriz.
- ncol: número de columnas de la matriz.
- byrow: le dice a R si los datos se llenarán por filas (
byrow = TRUE
) o por columnas (byrow = FALSE
). Este último es el valor por defecto.
Por ejemplo, podemos crear una matriz de dos filas y tres columnas de la siguiente manera:
# creando una matriz de dos filas por tres columnas
<- matrix( c(1, 2, 3, 3, 4, 5), nrow = 2, ncol = 3, byrow = FALSE)
m1 m1
## [,1] [,2] [,3]
## [1,] 1 3 4
## [2,] 2 3 5
# miramos la clase de este objeto
class(m1)
## [1] "matrix" "array"
También podemos crear una matriz combinando vectores de las mismas dimensiones; por ejemplo, creemos una matriz cuyas columnas sea los objetos v2
y v3
. Esto lo podemos hacer con la función cbind(). Esta función combina los vectores (columnas) (de ahí la c de columna y bind de unir) que se especifiquen como argumento de la función15; por ejemplo,
v2
## [1] 2.0 3.0 4.5 5.0 2.0 3.0 4.5 5.0 2.0 3.0 4.5 5.0
v3
## [1] 2.0 2.0 2.0 3.0 3.0 3.0 4.5 4.5 4.5 5.0 5.0 5.0
# creando una matriz uniendo los dos vectores como columnas
<- cbind(v2, v3)
m2 m2
## v2 v3
## [1,] 2.0 2.0
## [2,] 3.0 2.0
## [3,] 4.5 2.0
## [4,] 5.0 3.0
## [5,] 2.0 3.0
## [6,] 3.0 3.0
## [7,] 4.5 4.5
## [8,] 5.0 4.5
## [9,] 2.0 4.5
## [10,] 3.0 5.0
## [11,] 4.5 5.0
## [12,] 5.0 5.0
# miramos la clase de este objeto
class(m2)
## [1] "matrix" "array"
Con las matrices podemos hacer numerosas operaciones similares a las discutidas en la sección 4.2. En el Cuadro 5.2 se presenta un resumen de las principales operaciones que se pueden realizar con los objetos de clase matrix.
Operación | Ejemplo | Función o Código en R |
---|---|---|
Obtener el elemento \(i,j\) de una matriz | \(\mathbf{A}_{1,2}\) | A[1, 2] |
Transponer una matriz | \(\mathbf{A}^T\) | t(A) |
Determinante de una matriz cuadrada | \(\mathsf{det}\left(\mathbf{A}_{n \times n}\right)\) | det(A) |
Inversa de una matriz cuadrada | \(\mathbf{A}_{n \times n}^{-1}\) | solve(A) |
Elegir una columna | Columna 3 de la matriz \(\mathbf{A}\) | A[ , 3] |
Columna tiene nombre X | A$X | |
Elegir una fila | Fila 5 de la matriz \(\mathbf{A}\) Datos | A[5, ] |
Suma de matrices conformables | \(\mathbf{A}_{n \times m} + \mathbf{B}_{n \times m}\) | A + B |
Resta de matrices conformables | \(\mathbf{A}_{n \times m} - \mathbf{B}_{n \times m}\) | A - B |
Multiplicación de matrices conformables | \(\mathbf{A}_{n \times m} \times \mathbf{B}_{m \times k}\) | A %*% B |
Otra clase de objetos compuestos es array (arreglo en español). Un objeto de esta clase es similar a las matrices pero pueden tener más de dos dimensiones. Esto nos permite construir cubos de datos u objetos de datos con más de dos dimensiones. Por ejemplo, un objeto de clase array de dimensión (2, 3, 4) contiene 4 matrices cada una con 2 filas y 3 columnas. Un objeto de esta clase se crea con la función array() , la cuál tiene dos argumentos, los datos ( data) y las dimensiones ( dim).
Por ejemplo, creemos un objeto que contenga dos matrices, cada una con 3 filas y 3 columnas:
# creando un array de dos matrices cada una con
# 3 filas y 3 columnas
<- array(c(5, 9, 3, 10, 11, 12, 13, 14, 15),dim = c(3,3,2))
a1 a1
## , , 1
##
## [,1] [,2] [,3]
## [1,] 5 10 13
## [2,] 9 11 14
## [3,] 3 12 15
##
## , , 2
##
## [,1] [,2] [,3]
## [1,] 5 10 13
## [2,] 9 11 14
## [3,] 3 12 15
# miramos la clase de este objeto
class(a1)
## [1] "array"
Finalmente, discutamos la clase de objetos compuestas más útil para hacer análisis de datos: la clase data.frame. Esta clase es similar a las matrices, pero se entiende que cada columna corresponde a una variable y cada fila a las observaciones. Y su gran diferencia con una matriz es que cada variable (columna) puede ser de diferente clase.
Continuemos con el ejemplo con el cual empezamos, en aquel en el que registramos las ventas en millones de pesos durante el primer año de operación de la compañía de 4 clientes. En el objeto ventas_1
de clase numeric tenemos las ventas realizadas a cada cliente, en el objeto nombres
de clase character tenemos los nombres de los clientes y en el objeto sexo
de clase factor tenemos el sexo de cada cliente. Pongamos estas variables en una sola base de datos para su análisis posterior, empleando la función data.frame() .
# creando un data frame
<- data.frame(ventas_1, nombres, sexo)
d_ventas d_ventas
## ventas_1 nombres sexo
## 1 2.0 Juliana Femenino
## 2 3.0 Matías Masculino
## 3 4.5 Mariana Femenino
## 4 5.0 Luís Masculino
# miramos la clase de este objeto
class(d_ventas)
## [1] "data.frame"
Como lo realizamos anteriormente, podemos modificar el nombre de las variables (columnas) empleando la función names(); por ejemplo, cambiemos el nombre de la primera variable a solo ventas:
# cambiando el nombre d ela preimera variable
names(d_ventas)[1] <- "ventas"
d_ventas
## ventas nombres sexo
## 1 2.0 Juliana Femenino
## 2 3.0 Matías Masculino
## 3 4.5 Mariana Femenino
## 4 5.0 Luís Masculino
Ahora podemos ver la clase de cada una de las variables del objeto de clase data.frame. Esto lo podemos hacer rápidamente con la función str():
# constatando las clases de cada variable en el data frame
str(d_ventas)
## 'data.frame': 4 obs. of 3 variables:
## $ ventas : num 2 3 4.5 5
## $ nombres: chr "Juliana" "Matías" "Mariana" "Luís"
## $ sexo : Factor w/ 2 levels "Femenino","Masculino": 1 2 1 2
En el caso de los objetos de clase data.frame, así como de los objetos de clase lista, matrix y array, se pueda acceder a una columna (variable) empleando el signo $
entre el nombre del objeto y el nombre de la variable. Veamos un ejemplo16 .
# constatando la clase de cada variable en el data frame
class(d_ventas$sexo)
## [1] "factor"
También podemos acceder a un dato específico, como lo hacemos en el caso de las matrices, empleando los corchetes. El siguiente ejemplo muestra el segundo dato de la variable que se encuentra en la tercera columna. Recuerda que el primer elemento representa la fila y el segundo después de la coma es la columna:
# extrayendo el segundo dato de la variable que se encuentra
# en la tercera columna
2,3] d_ventas[
## [1] Masculino
## Levels: Femenino Masculino
O podemos ver una observación completa (fila). Extraigamos la segunda observación con todos sus datos para las variables:
# extrayendo la segunda observación para todas las variables
2,] d_ventas[
## ventas nombres sexo
## 2 3 Matías Masculino
Recomendación de Estilo
Emplea en los nombres de los objetos sólo letras minúsculas, números y _
. No emplees tildes ni la letra “eñe”. Los nombres de los objetos pueden ser sencillos, una sola letra o sustantivos, pero no uses verbos (estos se reservan para las funciones). Intenta que los nombres sean cortos y con significado. Si se requiere, utiliza los guiones bajos para separar las palabras dentro de un nombre.
Siempre que sea posible, evita utilizar nombres de objetos ya usados por R y sus paquetes; por ejemplo, evita emplear el nombre data
para los data.frames
.
# Buena práctica
empleados_hora
# Mala práctica
empleadosHora empleados_por_hora_para_el_primer_mes
5.3 Comentarios finales
En este capítulo discutimos diferentes clases de objetos que te permitirán trabajar en un futuro con otras clases. De hecho, existen innumerables clases de objetos, pero con lo que hemos visto aquí te podrás defender fácilmente en tu proceso de aprendizaje de este lenguaje.
Tal vez la clase de objeto más importante para trabajar con datos es el data.frame. Aquí vimos cómo construir de manera muy manual un data.frame, pero este no es el caso en la mayoría de las aplicaciones. Normalmente, las bases de datos se encuentran en archivos aparte. En el Capítulo 8 veremos cómo crear objetos de clase data.frame leyendo datos de archivos o leyendo datos de paquetes. Pero antes, en el Capítulo 7 discutiremos un poco más sobre las funciones que vienen en paquetes especiales. Y en el Capítulo @\(\ref{Wdir}\) hablaremos del working directory.