Clase 3


Matrices

En clases anteriores hemos abordado ya el concepto de vector. Lo que veremos ahora es la idea detrás de las matrices. Las matrices pueden entenderse como vectores de dos dimensiones, donde a los vectores le asociamos una dimensión de \(1\times n\), donde \(n\) es el número de entradas que tiene dicho vector. Por ejemplo

# vector de dimension 1x2
v1 <- c(0,0)
v2 <- c(1,4)

# vector de dimension 1x4
v3 <- c(1,4,5,8)

# vector de dimension 1x100
v4 <- c(1:100)

el hecho de que la dimensión sea \(1\times n\) en los vectores es debido a que un vector puede considerarse como una sola fila de datos. Escalando a otra dimensión, podremos considerar vectores de dimensión \(m\times n\), que puede entenderse como un conjunto de \(m\) vectores (o filas), que cada uno tiene \(n\) entradas. Por ejemplo

\[ \left(\begin{array}{cc} 1&0\\ 0&1 \end{array}\right) \]

es una matriz de \(2\times 2\), o también puede decirse que son dos vectores, \((1 \ \ 0)\) y \((0\ \ 1)\), que tienen dos entradas cada uno. De hecho, con las funciones rbind y cbind podemos crear matrices:

# Matriz de 2x2
matriz1 <- rbind(v1, v2)
matriz1
##    [,1] [,2]
## v1    0    0
## v2    1    4
# Matriz de 2x2
matriz2 <- cbind(v1, v2)
matriz2
##      v1 v2
## [1,]  0  1
## [2,]  0  4

Podemos crear explícitamente matrices utilizando la función matrix() como sigue

# Le pasamos un vector de numeros, los cuales acomodaremos en 3 filas por 3 columnas, lo cual nos da como resultado una matriz de 3x3.
# Especificamos el numero de filas y columnas

matriz3 <- matrix(1:9, nrow = 3, ncol = 3)
matriz3
##      [,1] [,2] [,3]
## [1,]    1    4    7
## [2,]    2    5    8
## [3,]    3    6    9

A la matriz anterior le podemos agregar una columna nueva con la función cbind:

# Definimos un vector con tres entradas
v5 <- 1:3

# Le agregamos dicho vector a la matriz3
cbind(matriz3, v5)
##            v5
## [1,] 1 4 7  1
## [2,] 2 5 8  2
## [3,] 3 6 9  3

Así como en los vectores, las operaciones con las matrices son entrada a entrada.

# A cada entrada le sumaremos un 7
matriz3 + 7
##      [,1] [,2] [,3]
## [1,]    8   11   14
## [2,]    9   12   15
## [3,]   10   13   16
# A cada entrada la multiplicamos por un 4
matriz3 * 4
##      [,1] [,2] [,3]
## [1,]    4   16   28
## [2,]    8   20   32
## [3,]   12   24   36

Podemos sumar, entrada a entrada, dos matrices

# Definimos otra matriz de 3x3
matriz4 <- matrix(10:18, nrow = 3, ncol = 3)

# Sumamos
matriz3 + matriz4
##      [,1] [,2] [,3]
## [1,]   11   17   23
## [2,]   13   19   25
## [3,]   15   21   27
# Multiplicamos
matriz3 * matriz4
##      [,1] [,2] [,3]
## [1,]   10   52  112
## [2,]   22   70  136
## [3,]   36   90  162

etcétera.

Considerando la matriz de \(2\times 3\)

ma <- matrix(1:6, nrow = 2, ncol = 3)
ma
##      [,1] [,2] [,3]
## [1,]    1    3    5
## [2,]    2    4    6

podemos obtener, a partir de dicha matriz, otra matriz de \(3\times 2\) con la función t():

# t(): funcion para transponer
t(ma)
##      [,1] [,2]
## [1,]    1    2
## [2,]    3    4
## [3,]    5    6

donde las filas de ma pasaron a ser columnas, lo cual invirtió el orden de la dimensión. En general, dada una matriz de dimensión \(m\times n\), al aplicar una operación de transpuesta obtendremos una matriz de \(n\times m\), cambiando las filas por columnas.

Finalmente, con la fucnión dim() obtenemos la dimensión de una matriz

# Dimension de la matriz ma
dim(ma)
## [1] 2 3
# Dimension de la transpuesta de la matriz ma
dim(t(ma))
## [1] 3 2

Cabe mencionar que en las matrices y en los vectores solo se admite un tipo de dato para todas las entradas, quedándose el tipo de dato de mayor jerarquía. Por ejemplo, si consideramos

v6 <- c(1, "Msj")
v6
## [1] "1"   "Msj"

tenemos que el número 1 ahora es considerado, dentro del vector v6 , como una cadena de texto. Lo mismo pasaría si definimos en una matriz números y cadenas de texto. De tal manera, estas estructuras de datos solo admiten un tipo de dato para todas sus entradas.

Lectura de datos

Dentro de R existen librerías que traen funcionalidades adicionales. Por ejemplo, en la librería datasets vienen integrados varios conjuntos de datos, por ejemplo:

# Cargamos la libreria datasets para poderla utilizar
library(datasets)

# De la libreria datasets accedemos al conjunto de datos iris
data <- datasets::iris

# Veamos
head(data)

con la función head() solo vemos la información de las primeras 6 filas. O podemos especificar el número de filas que queremos ver si escribimos head(data, 10) para ver las 10 primeras filas.

Podemos acceder a la información de una columna en específico, pero antes de ello obtengamos los nombres de todas las columnas:

# colnames(): nos regresa el nombre de todas las columnas
colnames(data)
## [1] "Sepal.Length" "Sepal.Width"  "Petal.Length" "Petal.Width"  "Species"

luego

# Vemos los primeros 6 valores de la columna Petal.Length escribiendo para ello data$Petal.Length

head(data$Petal.Length)
## [1] 1.4 1.4 1.3 1.5 1.4 1.7

esto es, dado un conjunto de datos, accedemos a los elementos de una columna utilizando el símbolo $. Adicionalmente, podemos acceder a un número determinado de filas y columnas:

# Entre corchetes escribimos:
# [numero de fila, numero de columna]
data[1, 3]
## [1] 1.4

O también podemos obtener rangos de filas y/o de columnas

# Datos de la fila 1 a la 3 considerando solo las columnas de la 2 a la 5
data[1:3, 2:5]

Podemos obtener la información de todas las columnas para cierto número de filas

# Seleccionamos de la fila 1 a la 3, pero todas las columnas
data[1:3, ]

o seleccionar todas las filas para ciertas columnas

# Todas las filas para las primeras 3 columnas
data[, 1:3]

En vez de utilizar vectores de secuencias seguidas (1,2,3), podemos utilizar:

# Todas las filas de las columnas 1 y 4
data[, c(1, 4)]

o, en vez de utilizar números para referirnos a las columnas, podemos utilizar directamente sus nombres

# Todas las filas de las columnas 1 y 4
data[, c("Sepal.Length", "Petal.Width")]

Podemos seleccionar información con base en una condición. Por ejemplo, seleccionar los elementos donde los valores de "Sepal.Length" sea mayores a 5:

# Entre corchetes ponemos la condicion.
# Accederemos a la columna Sepal.Length:
data[data$Sepal.Length > 5, ]

donde seleccionamos las filas que cumplían dicha condición y seleccionamos todas las columnas. Otro ejemplo:

# Seleccionamos toda la informacion donde la especie sea setosa
data[data$Species == "setosa", ]

Observamos que el conjunto de datos con el que estamos trabajando tiene 50 filas. Luego, podemos agregar columnas nuevas a nuestros conjuntos de datos, para ello escribiremos nombre_dataset$nombre_columna_nueva y asignaremos los valores que queremos agregar a esa columna nueva. Por ejemplo, agregaremos una columna nueva a data que tenga los números del 1 al 50

# Agregamos una columna nueva
data$ID <- 1:50

# Veamos
head(data$ID)
## [1] 1 2 3 4 5 6

Podemos eliminiar columnas. Para ello necesitaremos de dos componentes: los nombres de las columnas del dataset y un vector que tenga los nombres de las columnas que queremos eliminar. Por ejemplo

!( colnames(data) %in% c("Petal.Width", "Species", "ID") )

nos dice que, no queremos considerar la información de las columnas cuyos nombres estén en el vector c("Petal.Width", "Species", "ID"), lo cual significa, básicamente, que queremos eliminar dichas columnas. Recordemos que ! es el operador de negación not. De tal manera:

# Consideraremos un dataset sin las columnas "Petal.Width" "Species" y "ID". El dataset resultante lo almacenaremos en un nuevo dataser denominado dataset2:

data2 <- data[, !(colnames(data) %in% c("Petal.Width", "Species", "ID"))]
data2

Alternativamente podemos escribir

data3 <- data[, (colnames(data) %in% c("Sepal.Length", "Sepal.Width", "Petal.Length"))]
data3

que nos arroja la información de únicamente las columnas "Sepal.Length", "Sepal.Width" y "Petal.Length".

Luego, podemos ordenar los elementos de una columna:

# Obtenemos la informacion ordenada de menor a mayor de acuerdo a la columna Sepal.Length
data[order(data$Sepal.Length), ]

o también ordenar de mayor a menor

# Obtenemos la informacion ordenada de mayor a menor de acuerdo a la columna Sepal.Length
data[order(data$Sepal.Length, decreasing = TRUE), ]

Dataframes

El conjunto de datos iris con el cual hemos estado trabajando tiene almacenada la información en un tabla. Básicamente podemos entender a los dataframes como datos tabulares o tablas, de modo que la variable data es en realidad un dataframe. Podría pensarse también que un dataframe es como una matriz, pero en ésta se admiten distintos tipos de datos.

Luego, en la sección pasada estuvimos indagando un poco sobre las propiedades de un dataframe, vimos como realizar filtros de información y cómo implementar filtros con condiciones, y vimos como agregar columnas nuevas. Todo lo anterior lo hicimos cargando el dataset. Ahora lo que veremos es cómo crear un dataframe desde cero, para lo cual utilizaremos la función data.frame() como sigue

# Creamos nuestro primer dataframe
df1 <- data.frame(
  # El nombre de las columna ira como cadena de texto. A la primer columna le asigaremos los numeros del 1 al 4
  "Columna 1" = 1:4,
  "Columna 2" = c("a", "b", "c", "d"),
  "columna 3" = c(T, T, F, T)
)

# Veamos el dataframe
df1

Dado un dataframe podemos:

# Ver su dimension (filas  x columnas)
dim(df1)
## [1] 4 3
# Ver los nombres las columnas:
# Forma 1
names(df1)
## [1] "Columna.1" "Columna.2" "columna.3"
# Forma 2
colnames(df1)
## [1] "Columna.1" "Columna.2" "columna.3"

Es preciso mencionar que NO podremos realizar operaciones vectorizadas con los dataframes

df1 * 4
## Error in FUN(left, right): argumento no-numérico para operador binario

Luego, podemos importar dataframes de tablas de Excel o de archivos csv (valores separados por comas):

# Para leer documentos de excel necesitamos la siguiente libreria
library(readxl)

# Con la siguiente funcion leemos archivos de Excel
df <- read_excel(<<ruta del archivo>>)

En resumen, sabemos crear dataframes, sabemos obtener datasets de la librería datasets de R, conocemos las funciones para importar información de archivos Excel y csv. Además, tenemos las bases para manipular dataframes. Todo lo anterior constituye un primer, e importante paso, en la manipulación de datos con R, donde en clases posteriores iremos indagando en más técnicas y conociendo más herramientas que nos permitirán realizar una mejor manipulación de los datos con los que trabajemos.

Ejercicios

  1. Crea 4 vectores con 5 entradas, donde dichas entradas sean números aleatorios entre el 1 y el 10. Luego, a partir de ellos crea dos matrices de \(2\times 5\) utilizando la función rbind(). Con las dos matrices resultantes, calcula: la suma, resta y producto entre ellas.

  2. Utilizando una matriz que definiste en el punto anterior, obtén su dimensión y define una variable nueva que almacene la transpuesta de dicha matriz.

  3. Utilizando la librería datasets, carga el conjunto de datos airquality.

  • La columna Temp hace alusión a la temperatura. Encuentra el día más caluroso y más frio almacenado en ese conjunto de datos.
  • De acuerdo al número de filas de dicho dataset, agrega una columna nueva referente a un rango de números enteros que comience en el 1.
  • Obtén la información del dataset pero solo para las primeras 4 filas.
  • Obtén la información del dataset pero solo para las primeras dos columnas.
  • Define un nuevo dataset elminando las columnas Wind y Ozone.
  1. Crea un dataframe que contenga tres columnas. Decide cuál información quieres agregar a cada una de ellas. Adicionalmente, agrega una columna nueva denominada ID que contenga un rango de números que comience en 1.