Cosa mostra un istogramma
Un istogramma risponde a una domanda su una variabile numerica: come sono distribuiti i valori? Divide l'intervallo dei dati in intervalli consecutivi (classi, o bin), conta quante osservazioni cadono in ciascuno e disegna una barra per classe, alta quanto quel conteggio. Dove i dati sono fitti le barre sono alte; dove sono radi, sono basse.
Quell'unica immagine ti dice cose che media e deviazione standard non possono dirti: se i dati hanno uno o due picchi, se sono simmetrici o sbilanciati verso una coda, e se ci sono valori isolati lontani dal resto. Di solito è il primissimo grafico da fare quando incontri un nuovo dataset, insieme ai numeri della statistica descrittiva.
In R la funzione è hist(), e basta una riga.
Il tuo primo istogramma con hist()
Simuliamo l'altezza di 200 persone, con distribuzione normale intorno a 170 cm e deviazione standard 10 (vedi numeri casuali per sapere cosa fanno set.seed() e rnorm()):
set.seed(42)
heights <- rnorm(200, mean = 170, sd = 10)
hist(heights)
R sceglie da solo le classi e disegna una pila di barre a forma di campana: barre basse vicino a 145 cm, che crescono lungo i 160, raggiungono il picco intorno a 170 e scendono in modo simmetrico oltre i 190. L'asse verticale ha l'etichetta "Frequency", cioè i conteggi grezzi, e il titolo e l'etichetta dell'asse vengono dal nome della variabile.
Le impostazioni predefinite sono volutamente spartane. I soliti argomenti di abbellimento funzionano tutti:
hist(heights,
main = "Distribution of heights",
xlab = "Height (cm)",
col = "steelblue",
border = "white")
col riempie le barre, border colora i loro contorni: border = "white" dà l'aspetto pulito a barre separate che vedi nella maggior parte delle pubblicazioni. Tutto ciò che la guida a plot() dice su colori e titoli vale anche qui senza modifiche.
Larghezza delle classi: l'argomento breaks
L'argomento più importante di hist() è breaks, perché la larghezza delle classi decide quale storia racconta il grafico. Stessi dati, due impostazioni:
hist(heights, breaks = 5) # five wide bins: a crude, blocky bell
hist(heights, breaks = 30) # thirty narrow bins: detail, plus noise
Con breaks = 5 l'istogramma è così grossolano che tutto sembra un'unica gobba liscia: un secondo gruppo o un vuoto nei dati sarebbero invisibili. Con breaks = 30 vedi la struttura fine, ma le oscillazioni casuali iniziano a travestirsi da caratteristiche reali. Nessuna delle due è "corretta"; la mossa onesta è provare qualche impostazione e vedere quali caratteristiche sopravvivono.
breaks accetta tre forme:
- Un numero:
breaks = 30è un suggerimento per il numero di classi. R lo aggiusta per cadere su limiti ordinati, quindi potresti ottenere 28 o 33 classi. Sorprende tutti, almeno una volta. - Un vettore di punti di taglio:
breaks = seq(140, 200, by = 5)fissa i bordi esatti delle classi, senza trattative. Usalo quando le classi devono essere allineate tra più istogrammi che stai confrontando. - Il nome di una regola:
breaks = "FD"per Freedman-Diaconis, che sceglie la larghezza in base alla dispersione dei dati e alla dimensione del campione e si comporta bene con dati asimmetrici.
Istogrammi di densità e curva normale
Di default le altezze delle barre sono conteggi (freq = TRUE). Impostando freq = FALSE le barre vengono riscalate in modo che la loro area totale sia 1: la scala di densità. La forma non cambia, cambia l'asse verticale. Il motivo per farlo è che un istogramma di densità sta sulla stessa scala di una funzione di densità di probabilità, quindi puoi sovrapporre una curva teorica direttamente sopra i dati:
hist(heights,
freq = FALSE,
col = "gray90",
main = "Heights vs. a normal curve",
xlab = "Height (cm)")
curve(dnorm(x, mean = mean(heights), sd = sd(heights)),
add = TRUE, col = "tomato", lwd = 2)
curve() con add = TRUE disegna la curva a campana sopra l'istogramma esistente (la x dentro dnorm(x, ...) è un segnaposto che curve() riempie da sé, non una tua variabile). Se le barre aderiscono alla curva, un modello normale è ragionevole; dove se ne discostano, con una coda pesante o un secondo picco, al modello manca qualcosa. Senza freq = FALSE la curva striscia inutilmente sul fondo del grafico, perché conteggi e densità stanno su scale diverse.
I numeri dietro le barre
hist() non si limita a disegnare: restituisce la suddivisione in classi come lista. Con plot = FALSE salta del tutto il disegno e calcola soltanto, quindi questo lo puoi eseguire proprio qui:
h$counts è l'istogramma sotto forma di dati: ogni numero è l'altezza di una barra. La riga table(cut(...)) è l'equivalente in modalità testo: cut() divide i valori in classi, table() conta ogni classe, ed è un buon controllo da stampare prima di un grafico o al suo posto. Se assegni senza plot = FALSE (h <- hist(heights)), R disegna e restituisce la lista; l'assegnazione non sopprime il grafico.
Istogrammi con ggplot2
La versione ggplot2 sostituisce breaks con binwidth, che spesso è la manopola più naturale: dici quanto è larga una classe nelle unità dei dati invece di quante classi vuoi:
library(ggplot2)
ggplot(data.frame(heights), aes(x = heights)) +
geom_histogram(binwidth = 5, fill = "steelblue", color = "white") +
labs(title = "Distribution of heights", x = "Height (cm)", y = "Count")
binwidth = 5 significa che ogni barra copre 5 cm. ggplot2 ti avvisa se lasci binwidth non impostato e usa in silenzio 30 classi di default: dai retta all'avviso, perché quel valore raramente è la larghezza giusta per i tuoi dati. Per un'occhiata veloce a una variabile, hist() richiede meno battute; ggplot2 si guadagna il posto quando l'istogramma ha bisogno di facet, gruppi o un tema coerente con il resto delle tue figure.
Cosa ti porti a casa
- Un istogramma mostra la distribuzione di una variabile numerica:
hist(x)e hai finito. breaksè l'argomento che conta: un numero è solo un suggerimento, un vettore fissa i bordi esatti,"FD"sceglie una larghezza difendibile. Prova sempre più di un'impostazione.freq = FALSEpassa alla scala di densità, ed è ciò che permette acurve(dnorm(...), add = TRUE)di sovrapporre una curva normale in modo sensato.hist(x, plot = FALSE)restituisce le classi come dati ($breaks,$counts,$mids);table(cut(x, breaks))è l'equivalente solo testo.- In ggplot2,
geom_histogram(binwidth = ...), e impostabinwidthtu stesso.
Prossimo passo: il boxplot, il grafico di distribuzione che dà il meglio quando confronti gruppi uno accanto all'altro.
Domande frequenti
Come si fa un istogramma in R?
Chiama hist(x) su un vettore numerico. R divide l'intervallo di x in classi (bin) e disegna una barra per classe, la cui altezza mostra quanti valori ci cadono dentro. Aggiungi breaks = per controllare il numero di classi e col = per colorare le barre.
Cosa fa l'argomento breaks in hist()?
Controlla la suddivisione in classi. Un singolo numero come breaks = 30 è un suggerimento su quante classi usare (R lo arrotonda a limiti ordinati), un vettore come breaks = seq(140, 200, by = 5) fissa i punti di taglio esatti, e breaks = "FD" usa la regola di Freedman-Diaconis.
Come si sovrappone una curva normale a un istogramma in R?
Disegna l'istogramma sulla scala di densità con freq = FALSE, poi aggiungi la curva con curve(dnorm(x, mean = mean(data), sd = sd(data)), add = TRUE). Sulla scala delle frequenze la curva resterebbe inutilmente schiacciata vicino allo zero, quindi freq = FALSE è indispensabile.
Qual è la differenza tra un istogramma e un grafico a barre?
Un istogramma divide in classi una variabile numerica, quindi l'asse orizzontale è una scala continua e le barre si toccano. Un grafico a barre confronta categorie distinte, quindi le barre sono separate. In R si usa hist() per i numeri e barplot() per i conteggi delle categorie.