Menu

Matrices en R: matrix(), cbind, rbind y álgebra matricial

Cómo construir matrices con matrix(), cbind() y rbind(), indexar filas y columnas y mantener el * elemento a elemento separado de la verdadera multiplicación matricial %*%.

Esta página incluye editores ejecutables: edita, ejecuta y ve el resultado al instante.

Una matriz es un vector con dimensiones

Una matriz en R es un rectángulo de valores - filas y columnas - donde cada celda guarda el mismo tipo, normalmente números. Por dentro es literalmente un vector con un atributo dim grapado encima, lo que explica la mayor parte de su comportamiento: un solo tipo en todo, cálculos vectorizados en todas partes.

Construyes una reorganizando un vector con matrix():

Seis valores, dos filas - R deduce que hacen falta tres columnas. dim() informa de ambas dimensiones a la vez como 2 3; nrow() y ncol() las dan por separado.

Fíjate bien en la matriz impresa: los valores van 1 2 bajando por la primera columna y luego 3 4 por la siguiente. R rellena las matrices columna a columna por defecto. Si tus datos se leen fila a fila - que es como suelen escribirlos las personas -, dilo con byrow = TRUE:

Ahora la primera fila es 1 2 3. Olvidar byrow = TRUE no da error - te da en silencio una disposición con aspecto de transpuesta de los mismos números, así que acostúmbrate a comprobar la distribución impresa siempre que construyas una matriz a partir de valores en bruto.

Indexación: m[fila, columna]

La indexación de matrices toma dos posiciones dentro de un mismo par de corchetes, la fila antes de la coma y la columna después - ambas contando desde 1:

Dejar una posición vacía significa "todas": m[1, ] es toda la primera fila y m[, 2] toda la segunda columna. Fíjate en que ambas vuelven como vectores normales - R elimina la dimensión que se colapsó a tamaño 1. Eso es cómodo de forma interactiva y una trampa en el código, porque una función que espera una matriz se atragantará con el vector. Pídele a R que conserve la forma con drop = FALSE:

dim() ahora informa de 1 3 - sigue siendo una matriz. Siempre que extraigas una sola fila o columna dentro de una función, escribe drop = FALSE; el bug que evita (código que funciona con datos anchos y se rompe con datos de una columna) es de los más miserables de rastrear.

Las máscaras lógicas también funcionan aquí: m[m > 3] devuelve todas las celdas por encima de 3, como un vector.

Construir con cbind() y rbind()

En lugar de reorganizar un vector largo, puedes ensamblar una matriz a partir de piezas: cbind() une vectores como columnas y rbind() como filas. Las mismas funciones también amplían una matriz existente:

Los nombres viajan con los vectores: cbind() usó heights y weights como nombres de columna automáticamente, lo que mantiene legible la matriz impresa. Ambas funciones insisten en que las longitudes encajen (con reciclaje para valores de longitud 1); unir un vector de longitud 3 a una matriz de 4 filas te avisa.

Los nombres de columnas y filas también se pueden fijar directamente con colnames(m) <- ... y rownames(m) <- ..., tras lo cual puedes indexar por nombre: people[, "weights"].

El * elemento a elemento frente a la verdadera multiplicación matricial %*%

Aquí está la distinción que más importa de todo este artículo. R tiene dos operadores de multiplicación para matrices, y calculan cosas totalmente distintas:

  • a * a es elemento a elemento: cada celda multiplicada por la celda correspondiente. 1 2 3 4 se convierten en 1 4 9 16, dispuestos con la misma forma. Esto no es más que aritmética vectorizada, el mismo * que usas con vectores.
  • a %*% a es la multiplicación de matrices del álgebra lineal - cada celda del resultado es una fila de la primera matriz por una columna de la segunda, sumadas. La misma entrada da 7 10 15 22: números completamente diferentes.

Ejecuta el fragmento y compara las dos salidas una al lado de la otra; ver cómo difieren con entradas idénticas es lo que hace que la distinción se quede. Si escribes * donde el cálculo pide %*%, R no te avisará - las formas son compatibles en ambos casos para matrices cuadradas - simplemente obtendrás números incorrectos. En código de estadística (matrices de covarianza, álgebra de modelos lineales) este es uno de los bugs silenciosos clásicos.

t() transpone - intercambia filas y columnas - y aparece constantemente junto a %*% porque la multiplicación de matrices necesita que las dimensiones interiores coincidan:

Para completar: solve(m) invierte una matriz, y %*% con un vector lo trata como una matriz de una columna. Eso es lo más lejos que necesita llegar la mayoría del trabajo con datos.

Resúmenes por filas y columnas

Sumar o promediar por filas y columnas es tan habitual que R incluye funciones dedicadas y rápidas para ello:

rowSums() colapsa cada fila a un número (6 15 aquí), colSums() cada columna (5 7 9), y las variantes Means promedian en lugar de sumar. Prefiérelas frente a bucles caseros o incluso a apply(m, 1, sum) - son más claras y más rápidas. Para resúmenes que estas cuatro no cubren (digamos, el máximo por columna), la familia apply es la herramienta general: apply(m, 2, max).

¿Matriz o data frame?

Ambos son rectangulares, así que ¿a cuál recurres?

  • Matriz: todas las celdas del mismo tipo y las matemáticas importan. Cálculo numérico, álgebra lineal, cálculos de distancias, rejillas tipo imagen. Las matrices son más ligeras y sus operaciones más rápidas precisamente por la garantía de un único tipo.
  • Data frame: columnas de tipos diferentes - nombres junto a edades junto a indicadores lógicos. Estos son los datos tabulares del mundo real, y es lo que esperan casi todas las funciones de análisis de datos.

Una buena regla: si lo abrirías de forma natural en una hoja de cálculo con columnas nombradas y mezcladas, es un data frame. Si es una rejilla de números sobre la que piensas hacer álgebra, es una matriz. Convertir entre ambos es fácil (as.matrix(), as.data.frame()) - pero as.matrix() sobre un data frame con alguna columna de texto coacciona todo a carácter, así que convierte solo las columnas numéricas.

Lo que te llevas

  • Una matriz es un vector con dimensiones: un solo tipo en todo, construida con matrix(data, nrow, ncol) - y se rellena columna a columna salvo que pases byrow = TRUE.
  • Indexa como m[fila, columna]; una posición vacía significa "todas"; añade drop = FALSE al extraer filas o columnas sueltas dentro del código.
  • cbind() y rbind() ensamblan matrices a partir de vectores o amplían las existentes.
  • * es elemento a elemento, %*% es la multiplicación matricial real - mismas entradas, respuestas distintas, ningún aviso.
  • rowSums() / colSums() / rowMeans() / colMeans() cubren los resúmenes del día a día.

Lo siguiente: los factores - cómo representa R los datos categóricos, y las trampas que traen consigo.

Preguntas frecuentes

¿Cómo se crea una matriz en R?

matrix(1:6, nrow = 2) reorganiza un vector en 2 filas y 3 columnas, rellenando columna a columna. Añade byrow = TRUE para rellenar fila a fila. También puedes ensamblar una matriz a partir de vectores: cbind() los pega como columnas y rbind() como filas.

¿Cuál es la diferencia entre * y %*% en R?

* multiplica elemento a elemento - cada celda por la celda correspondiente, y las formas deben encajar. %*% es la verdadera multiplicación de matrices del álgebra lineal (filas por columnas, así que las dimensiones interiores deben coincidir). Dan resultados completamente distintos sobre las mismas matrices, y usar * donde querías decir %*% es un bug silencioso clásico.

¿Cómo se obtiene una fila o una columna de una matriz en R?

Deja vacía la otra posición: m[1, ] es la primera fila y m[, 2] la segunda columna. Ambas vuelven como vectores normales por defecto. Añade drop = FALSE - como en m[1, , drop = FALSE] - para conservar el resultado como una matriz de una fila o una columna, lo que importa cuando el código posterior espera dos dimensiones.

Coddy programming languages illustration

Aprende a programar con Coddy

COMENZAR