Menu

Matrici in R: matrix(), cbind, rbind e calcolo matriciale

Come costruire matrici con matrix(), cbind() e rbind(), indicizzare righe e colonne e tenere distinto il * elemento per elemento dalla vera moltiplicazione matriciale %*%.

Questa pagina include editor eseguibili: modifica, esegui e vedi subito l'output.

Una matrice è un vettore con dimensioni

Una matrice in R è un rettangolo di valori, con righe e colonne, in cui ogni cella contiene lo stesso tipo, di solito numeri. Sotto il cofano è letteralmente un vettore con un attributo dim attaccato sopra, e questo spiega gran parte del suo comportamento: un solo tipo ovunque, calcoli vettorizzati ovunque.

Ne costruisci una rimodellando un vettore con matrix():

Sei valori, due righe: R capisce da solo che servono tre colonne. dim() riporta entrambe le dimensioni insieme come 2 3; nrow() e ncol() le danno separatamente.

Guarda bene la matrice stampata: i valori scorrono 1 2 lungo la prima colonna, poi 3 4 lungo la successiva. Di default R riempie le matrici colonna per colonna. Se i tuoi dati si leggono riga per riga, che è il modo in cui di solito li scriviamo, dillo con byrow = TRUE:

Ora la prima riga è 1 2 3. Dimenticare byrow = TRUE non dà errore: ti restituisce in silenzio una disposizione degli stessi numeri che sembra trasposta, quindi prendi l'abitudine di controllare il layout stampato ogni volta che costruisci una matrice da valori grezzi.

Indicizzazione: m[row, column]

L'indicizzazione delle matrici usa due posizioni dentro una sola coppia di parentesi quadre, la riga prima della virgola e la colonna dopo, entrambe contando da 1:

Lasciare vuota una posizione significa "tutte": m[1, ] è l'intera prima riga, m[, 2] l'intera seconda colonna. Nota che entrambe tornano come semplici vettori: R elimina la dimensione che si è ridotta a 1. È comodo in modo interattivo e una trappola nel codice, perché una funzione che si aspetta una matrice si blocca sul vettore. Chiedi a R di mantenere la forma con drop = FALSE:

Ora dim() riporta 1 3: è ancora una matrice. Ogni volta che estrai una singola riga o colonna dentro una funzione, scrivi drop = FALSE; il bug che previene (codice che funziona su dati larghi e si rompe su dati con una sola colonna) è di quelli terribili da scovare.

Anche le maschere logiche funzionano: m[m > 3] restituisce tutte le celle maggiori di 3, come vettore.

Costruire con cbind() e rbind()

Invece di rimodellare un unico vettore lungo, puoi assemblare una matrice a pezzi: cbind() unisce i vettori come colonne, rbind() come righe. Le stesse funzioni estendono anche una matrice esistente:

I nomi viaggiano con i vettori: cbind() ha usato automaticamente heights e weights come nomi di colonna, e questo mantiene leggibile la matrice stampata. Entrambe le funzioni pretendono che le lunghezze combacino (con il riciclo per i valori di lunghezza 1); unire un vettore di lunghezza 3 a una matrice di 4 righe produce un avviso.

I nomi di colonna e di riga si possono anche impostare direttamente con colnames(m) <- ... e rownames(m) <- ..., dopodiché puoi indicizzare per nome: people[, "weights"].

* elemento per elemento contro la vera moltiplicazione matriciale %*%

Ecco la distinzione che conta di più in tutto l'articolo. R ha due operatori di moltiplicazione per le matrici, e calcolano cose del tutto diverse:

  • a * a è elemento per elemento: ogni cella moltiplicata per la cella corrispondente. 1 2 3 4 diventano 1 4 9 16, disposti nella stessa forma. È semplice aritmetica vettorizzata, lo stesso * che usi sui vettori.
  • a %*% a è la moltiplicazione matriciale dell'algebra lineare: ogni cella del risultato è una riga della prima matrice per una colonna della seconda, sommate. Lo stesso input dà 7 10 15 22: numeri completamente diversi.

Esegui il frammento e confronta i due output fianco a fianco; vederli diversi su input identici è ciò che fissa la distinzione. Se scrivi * dove la matematica richiede %*%, R non ti avvisa (per le matrici quadrate le forme sono compatibili in entrambi i casi): ottieni solo numeri sbagliati. Nel codice statistico (matrici di covarianza, algebra dei modelli lineari) è uno dei classici bug silenziosi.

t() traspone, cioè scambia righe e colonne, e compare di continuo accanto a %*% perché la moltiplicazione matriciale richiede che le dimensioni interne coincidano:

Per completezza: solve(m) inverte una matrice, e %*% con un vettore lo tratta come una matrice di una colonna. Per la maggior parte del lavoro sui dati non serve andare più a fondo.

Riepiloghi per righe e colonne

Sommare o fare la media lungo righe e colonne è così comune che R offre funzioni dedicate e veloci:

rowSums() riduce ogni riga a un numero (6 15 qui), colSums() ogni colonna (5 7 9), e le varianti Means calcolano la media. Preferiscile ai cicli scritti a mano e perfino ad apply(m, 1, sum): sono più chiare e più veloci. Per i riepiloghi che queste quattro non coprono (per esempio il massimo di ogni colonna), la famiglia apply è lo strumento generale: apply(m, 2, max).

Matrice o data frame?

Sono entrambi rettangolari, quindi quale scegli?

  • Matrice: ogni cella dello stesso tipo, e i calcoli contano. Calcolo numerico, algebra lineare, calcolo di distanze, griglie simili a immagini. Le matrici sono più leggere e le loro operazioni più veloci proprio grazie alla garanzia di un solo tipo.
  • Data frame: colonne di tipi diversi, con nomi accanto a età accanto a flag logici. Sono i dati tabellari del mondo reale, ed è quello che si aspettano quasi tutte le funzioni di analisi dei dati.

Una buona regola: se lo apriresti naturalmente in un foglio di calcolo con colonne con nome e di tipo misto, è un data frame. Se è una griglia di numeri su cui vuoi fare algebra, è una matrice. Convertire dall'uno all'altro è facile (as.matrix(), as.data.frame()), ma as.matrix() su un data frame con anche una sola colonna di testo converte tutto in carattere, quindi converti solo le colonne numeriche.

Cosa ti porti a casa

  • Una matrice è un vettore con dimensioni: un solo tipo ovunque, costruita con matrix(data, nrow, ncol), e si riempie colonna per colonna a meno che tu non passi byrow = TRUE.
  • Indicizza con m[row, col]; una posizione vuota significa "tutte"; aggiungi drop = FALSE quando estrai singole righe o colonne nel codice.
  • cbind() e rbind() assemblano matrici a partire da vettori o estendono quelle esistenti.
  • * è elemento per elemento, %*% è la vera moltiplicazione matriciale: stessi input, risposte diverse, nessun avviso.
  • rowSums() / colSums() / rowMeans() / colMeans() gestiscono i riepiloghi di tutti i giorni.

Prossimo passo: i factor, come R rappresenta i dati categorici e le trappole che si portano dietro.

Domande frequenti

Come si crea una matrice in R?

matrix(1:6, nrow = 2) rimodella un vettore in 2 righe e 3 colonne, riempiendolo colonna per colonna. Aggiungi byrow = TRUE per riempirlo invece riga per riga. Puoi anche assemblare una matrice a partire da vettori: cbind() li unisce come colonne, rbind() come righe.

Qual è la differenza tra * e %*% in R?

* moltiplica elemento per elemento: ogni cella per la cella corrispondente, e le forme devono combaciare. %*% è la vera moltiplicazione matriciale dell'algebra lineare (righe per colonne, quindi le dimensioni interne devono coincidere). Sulle stesse matrici danno risultati completamente diversi, e usare * dove intendevi %*% è un classico bug silenzioso.

Come si ottiene una riga o una colonna di una matrice in R?

Lascia vuota l'altra posizione: m[1, ] è la prima riga, m[, 2] è la seconda colonna. Di default tornano entrambe come semplici vettori. Aggiungi drop = FALSE, come in m[1, , drop = FALSE], per mantenere il risultato come matrice di una riga o di una colonna, cosa che conta quando il codice successivo si aspetta due dimensioni.

Illustrazione dei linguaggi di programmazione di Coddy

Impara a programmare con Coddy

INIZIA