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 4diventano1 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 passibyrow = TRUE. - Indicizza con
m[row, col]; una posizione vuota significa "tutte"; aggiungidrop = FALSEquando estrai singole righe o colonne nel codice. cbind()erbind()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.