Matrices en R

Introducción a R Estructuras de datos
Aprende a crear y manipular matrices en el lenguaje R

Una matriz en R es una estructura de datos para almacenar objetos del mismo tipo. Si quieres almacenar diferentes objetos dentro de una estructura de datos en R, usa un data frame en su lugar. En este tutorial mostraremos los principales usos y cálculos con matrices en R.

¿Cómo crear una matriz en R?

La función matrix permite una matriz en RStudio o R base, pasando como input un vector numérico, de caracteres o lógico.

data <- 1:6

# Creando la matriz
matrix(data)
      [, 1]
[1, ]    1
[2, ]    2
[3, ]    3
[4, ]    4
[5, ]    5
[6, ]    6

Como se puede apreciar en la salida, por defecto se creará una matriz de una columna y tantas filas como la longitud del vector. Sin embargo, es posible establecer el número de columnas o el número de filas con los argumentos ncol y nrow, respectivamente. También puedes especificar si la matriz está ordenada por filas o por columnas con el argumento byrow. Por defecto, la función ordenará la entrada por columnas (byrow = FALSE).

# Por columnas
matrix(data, ncol = 2, byrow = FALSE) # byrow = FALSE por defecto
matrix(data, ncol = 2, nrow = 3) # Equivalente
matrix(data, nrow = 3) # Equivalente

# Por filas
matrix(data, ncol = 2, byrow = TRUE)
# Por columnas             # Por filas
     [, 1] [, 2]                 [, 1] [, 2]
[1, ]   1    4             [1, ]    1    2
[2, ]   2    5             [2, ]    3    4
[3, ]   3    6             [3, ]    5    6

Ahora bien, si tienes datos almacenados en vectores o en las columnas de un data frame, puedes usar cbind para concatenar columnas o rbind para concatenar filas, siendo el output una matriz. La clase de la salida se puede comprobar con la función class y la clase de los elementos con la función typeof.

x <- c(2, 7, 3, 6, 1)
y <- c(3, 7, 3, 5, 9)

# Por columnas
cbind(x, y)

# Por filas
rbind(x, y)

# Clase de la salida
class(cbind(x, y))  # "matrix"

# Tipo de dato de los elementos
typeof(cbind(x, y)) # "double"
# Por columnas              # Por filas
      x   y                    [, 1] [, 2] [, 3] [, 4] [, 5]
[1, ] 2   3                 x    2     7     3     6     1   
[2, ] 7   7                 y    3     7     3     5     9
[3, ] 3   3
[4, ] 6   5
[5, ] 1   9

Ten en cuenta que puedes usar cualquier tipo de datos dentro de una matriz, siempre que sean homogéneos.

matrix(c(TRUE, TRUE, FALSE, TRUE), ncol = 2)
matrix(c("rojo", "verde", "naranja", "negro"), ncol = 2)
     [, 1]  [, 2]              [, 1]    [, 2]
[1, ] TRUE FALSE         [1, ] "rojo"  "naranja"
[2, ] TRUE  TRUE         [2, ] "verde" "negro"

Además, puedes conocer las dimensiones de la matriz con la función dim.

matriz <- matrix(1:12, ncol = 2, byrow = FALSE)

# Dimensiones de la matriz
dim(matriz) # 6 2

El primer número de la salida de la función dim indica el número de filas (6) y el segundo el número de columnas (2).

Ten en cuenta que la función dim también se puede utilizar para crear una matriz en R.

A <- c(3, 1, 6, 1, 2, 9)
dim(A) <- c(3, 2)
      [, 1] [, 2]
[1, ]    3     1
[2, ]    1     2
[3, ]    6     9

A modo esquemático, la siguiente tabla muestra las funciones más comunes relacionadas con matrices.

Función Descripción
dim(), nrow(), ncol() Número de filas/columnas
diag() Diagonal de una matriz
* Multiplicación elemento a elemento
%*% Producto matricial
%o% Producto exterior
%x% Producto de Kronecker
cbind(), rbind() Agregar filas/columnas
t() Matriz traspuesta
solve(A) Inversa de la matriz \(A\)
solve(A, b) Solución a \(Ax = b\)
eigen() Autovalores y autovectores
qr() Descomposición QR
chol() Descomposicion de Cholesky
svd() Descomposición singular

Añadir y eliminar columnas de matrices en R

Como mostramos antes, la función cbind puede usarse para crear una matriz. Sin embargo, el uso principal de la función es agregar columnas a las estructuras de datos. Para eliminar columnas, utiliza el operador - indicando el índice de la columna en el segundo argumento entre corchetes, como en el ejemplo.

# Añadir columna
A <- cbind(A, c(6, 1, 7))

# Añadir dos columnas
A <- cbind(A, c(6, 1, 7), c(1, 6, 1))

# Eliminar la primera columna
A <- A[, -1]

# Borrar la primera y la tercera columna
A <- A[, -c(1, 3)]

Añadir y eliminar filas a una matriz en R

Equivalentemente a la función anterior, la función rbind se puede usar para agregar filas a objetos. También puedes eliminar filas de la misma manera que antes, pero indicando el índice en el primer argumento entre corchetes.

# Agregar fila
A <- rbind(A, c(6, 1))

# Agregar fila de cincos
A <- rbind(A, 5)

# Eliminar la segunda fila
A <- A[-2, ]

Apilar matrices en R

La función rbind también se puede utilizar para apilar o combinar matrices:

x <- matrix(c(2, 7, 1, 3, 6, 1), ncol = 2, byrow = TRUE)
y <- matrix(c(3, 7, 6, 3, 5, 9), ncol = 2, byrow = TRUE)

# Apilando las matrices
rbind(x, y)
     [, 1] [, 2]
[1, ]    2    7
[2, ]    1    3
[3, ]    6    1
[4, ]    3    7
[5, ]    6    3
[6, ]    5    9

Además, si creas una lista de matrices en R y no conoces de antemano la longitud final que tendrá la lista, puedes usar la función do.call de la siguiente manera para unir las matrices:

lista_matrices <- list(x, y)
lista_matrices
[[1]]
     [,1] [,2]
[1,]    2    7
[2,]    1    3
[3,]    6    1

[[2]]
     [,1] [,2]
[1,]    3    7
[2,]    6    3
[3,]    5    9
do.call(rbind, lista_matrices)
rbind(lista_matrices[[1]], lista_matrices[[2]]) # Equivalente

El código anterior devolverá la misma salida que rbind(x, y), la diferencia es que con do.call no necesitamos saber el número de matrices que se apilarán. Si la lista contiene más matrices en su interior, la función seguirá funcionando.

Añadir nombres a las filas y a las columnas

Puedes cambiar los nombres de las filas y columnas de una matriz con las funciones rownames y colnames .

B <- matrix(c(4, 5, 1, 10, 8, 3),
             nrow = 2, ncol = 3, byrow = TRUE)

# Agregar nombres a las filas
rownames(B) <- c("Fila 1", "Fila 2")
rownames(B) <- paste0("Fila ", 1:nrow(B)) # Equivalente

# Agregar nombres a las columnas
colnames(B) <- c("Columna 1", "Columna 2", "Columna 3")
colnames(B) <- paste0("Columna ", 1:ncol(B)) # Equivalente
B
      Columna 1 Columna 2 Columna 3
Fila 1        4        5        1
Fila 2       10        8        3

Nótese que puedes renombrar las columnas y filas de la matriz de la misma manera.

Además, con la función attributes puedes acceder a la dimensión y los nombres de columna y fila de tu matriz.

attributes(B)
$`dim`
[1] 2 3

$dimnames
$dimnames[[1]]
[1] "Fila 1" "Fila 2"

$dimnames[[2]]
[1] "Columna 1" "Columna 2" "Columna 3"

Si solo quieres devolver los nombres de columna y fila, puedes utilizar la función dimnames y acceder a los elementos de la lista para tener los nombres de las filas o de las columnas.

dimnames(B)
[[1]]
[1] "Fila 1" "Fila 2"

[[2]]
[1] "Columna 1" "Columna 2" "Columna 3"

Eliminar nombres de las filas y las columnas de las matrices

En caso de que estés trabajando con una matriz con nombres y quieras deshacerte de ellos, simplemente puedes eliminar los nombres de las filas o columnas asignándoles el valor NULL o usando la función unname para borrar todos los nombres.

# Borrar nombres de las columnas
colnames(B) <- NULL

# Borrar nombres de las filas
rownames(B) <- NULL

# Eliminar nombres de 
# filas y columnas a la vez
unname(B)

Acceder a los elementos de una matriz en R

Acceder a los elementos de una matriz es similar a acceder a los elementos de un data frame en R. La principal manera para acceder a los datos es usar matriz[filas, columnas]. Sin embargo, existen ciertas diferencias entre las estructuras de datos.

matriz <- matrix(c(1, 5, 8, 1, 3, 2), ncol = 3)
matriz
      [, 1] [, 2] [, 3]
[1, ]    1    8     3
[2, ]    5    1     2
# Primer elemento de la primera columna
matriz[1]    # 1
matriz[[1]]  # Equivalente
matriz[1, 1] # Equivalente

# Segunda fila, tercera columna
matriz[2, 3] # 2

# Primera fila
matriz[1, ] # 1 8 3

# Segunda columna
matriz[, 2] # 8 1

# Primera y segunda columna, primera fila
matriz[1, 1:2] # 1 8

# Primera y tercera columna, segunda fila
matriz[2, c(1, 3)] # 5 2
matriz[2, c(TRUE, FALSE, TRUE)] # Equivalente

# Todas las columnas excepto la segunda
matriz[, -2]

# Última fila de la matriz
matriz[nrow(matriz), ] # 5 1 2

# Última columna de la matriz
matriz[, ncol(matriz)] # 3 2

Ten en cuenta que al devolver filas o columnas individuales, la salida será un vector. Si quieres evitar esto, establece drop = FALSE.

matriz[1, , drop = FALSE]
      [, 1] [, 2] [, 3]
[1, ]    1    8    3

Dejamos en blanco el segundo argumento porque estamos seleccionando todas las columnas.

Además, si la matriz tiene nombres, puedes acceder a los elementos indexándolos con los nombres.

C <- matrix(c(5, 3, 2, 52, 34, 12), nrow = 2, ncol = 3, byrow = TRUE)

rownames(C) <- c("Fila 1", "Fila 2")
colnames(C) <- c("Columna 1", "Columna 2", "Columna 3")

# Primera fila, columnas 1 y 3
C["Fila 1", c("Columna 1", "Columna 3")]
Columna 1 Columna 3
        5         2 

Eliminar valores NA, NaN e Inf de una matriz

En ocasiones tendrás que lidiar con valores perdidos u omitidos. Existen diferentes tipos como los valores NA (no disponible), NaN (no es un número) e Inf (infinito). Ten en cuenta que puedes eliminar las filas o columnas que contienen estos valores o reemplazarlos con otros valores. Considera la siguiente matriz:

C <- matrix(c(14, NaN, 3, Inf, -5, 4, 1, NA), ncol = 4)
C
      [, 1] [, 2] [, 3] [, 4]
[1, ]   14     3    -5     1
[2, ]  NaN   Inf     4    NA

Puedes eliminar las filas o las columnas con valores no finitos con las funciones rowSums o colSums e is.finite.

# Borrar todas las filas con valores no finitos
C[!rowSums(!is.finite(C)), ] # 14  3 -5  1

# Borrar todas las columnas con valores no finitos
C[, !colSums(!is.finite(C)), drop = FALSE]

En caso de que quieras reemplazar los valores, puedes detectar los valores no finitos usando !is.finite y los valores NA con la función is.na y luego asignar los valores que quieras. En este caso vamos a reemplazarlos con 0.

# Reemplazar los NA con 0
C[is.na(C)] <- 0
C
    [, 1] [, 2] [, 3] [, 4]
[1, ]   14    3   -5    1
[2, ]    0  Inf    4    0
# Reemplazar los valores no finitos con 0
C[!is.finite(C)] <- 0
C
     [,1] [,2] [,3] [,4]
[1,]   14    3   -5    1
[2,]    0    0    4    0