I grafici a barre confrontano categorie
Un grafico a barre risponde alla domanda "quanto di ciascuno?": una barra per categoria, con la lunghezza della barra che mostra il valore della categoria. In R la funzione di base è barplot(), e il suo input è semplicemente un vettore di altezze. Dai dei nomi al vettore e i nomi diventano le etichette sotto le barre:
visits <- c(Mon = 42, Tue = 51, Wed = 47, Thu = 60, Fri = 78)
barplot(visits,
main = "Store visits by day",
ylab = "Visits")
Cinque barre grigie, etichettate per giorno, che salgono da un lunedì modesto fino a un picco il venerdì alto quasi il doppio. Niente da installare, niente da configurare: se sai costruire un vettore con nomi, sai farne un grafico.
Gli editor eseguibili di questa pagina mostrano solo output testuale, quindi le chiamate a barplot() qui sono frammenti statici da incollare in una sessione R locale. Il passaggio di conteggio che le precede però funziona benissimo, ed è quello che conta di più.
Il flusso reale: prima table(), poi barplot()
In pratica raramente hai altezze già contate e in ordine. Hai una colonna grezza di etichette di categoria, una riga per risposta al sondaggio, per ordine, per utente, e il conteggio è il vero lavoro. table() lo fa in una chiamata, e il suo output è un vettore di conteggi con nomi, che è esattamente ciò che vuole barplot():
Poi il grafico è una riga in più:
barplot(sort(t, decreasing = TRUE),
main = "Survey responses",
ylab = "Count")
Questi due passi, table() e poi barplot(), sono il flusso più comune in assoluto per i grafici a barre in R. Ordinare prima la tabella è un miglioramento che non costa nulla: barre ordinate per altezza si leggono più in fretta di barre in ordine alfabetico, a meno che le categorie abbiano un ordine naturale (giorni, mesi, livelli di dose). In quel caso un factor con i livelli nell'ordine giusto impedisce a table() di metterli in ordine alfabetico. Per barre che richiedono una vera aggregazione, cioè somme o medie per gruppo invece di conteggi di righe, fai prima il passaggio di group-by-summarize e passa il risultato a barplot().
Etichette e stile
Di solito le etichette vengono dai nomi del vettore, ma names.arg le sostituisce: utile quando i codici nei dati non sono adatti a un pubblico:
barplot(visits,
names.arg = c("Monday", "Tuesday", "Wednesday",
"Thursday", "Friday"),
col = "steelblue",
border = NA,
main = "Store visits by day",
las = 2)
colriempie le barre; passa un vettore per colorare ogni barra singolarmente, ma resisti all'arcobaleno per default: il colore dovrebbe avere un significato, come evidenziare l'unica barra di cui stai parlando.border = NArimuove i contorni delle barre per un aspetto più pulito.las = 2ruota le etichette degli assi in perpendicolare all'asse: è la soluzione quando nomi di categoria lunghi si sovrappongono. Abbinalo a un margine inferiore più grande (par(mar = c(8, 4, 4, 2))) se i nomi sono davvero lunghi.
Barre raggruppate e impilate da una matrice
Per mostrare due dimensioni categoriali insieme, per esempio le vendite per canale e per trimestre, passa a barplot() una matrice. Ogni colonna diventa una posizione sull'asse delle categorie e le righe diventano le sotto-barre:
sales <- matrix(c(12, 18, 15, 22, 20, 19, 24, 27),
nrow = 2,
dimnames = list(c("Online", "Retail"),
c("Q1", "Q2", "Q3", "Q4")))
# Grouped: rows stand next to each other within each quarter
barplot(sales, beside = TRUE,
col = c("steelblue", "orange"),
legend.text = rownames(sales),
main = "Sales by channel and quarter")
# Stacked: rows pile up into one total bar per quarter (the default)
barplot(sales, beside = FALSE,
col = c("steelblue", "orange"),
legend.text = rownames(sales))
beside = TRUE mette i due canali fianco a fianco dentro ogni trimestre: la scelta migliore quando vuoi confrontare i canali direttamente. La versione impilata predefinita mette in risalto il totale di ogni trimestre, con la suddivisione mostrata dentro ogni barra; è onesta per i totali ma rende difficile confrontare i segmenti interni tra una barra e l'altra, perché le loro basi si spostano. legend.text = rownames(sales) aggiunge la legenda che rende leggibili entrambe le versioni.
Un'altra opzione: horiz = TRUE dispone le barre lungo l'asse orizzontale. È il layout più gentile quando hai molte categorie con nomi lunghi: ogni etichetta sta sulla sua riga accanto alla sua barra, senza bisogno di ruotarla.
Grafico a barre o istogramma?
Chi cerca li confonde di continuo, e la distinzione vale trenta secondi: un grafico a barre confronta categorie distinte. L'asse è un insieme di etichette, le barre sono separate e riordinarle è lecito. Un istogramma raggruppa in classi una variabile numerica. L'asse è una scala continua, le barre si toccano perché le classi sono intervalli consecutivi e riordinarle non avrebbe senso. Se la tua colonna contiene parole ("Yes", "Chrome", "Q3"), ti serve barplot(table(x)). Se contiene misure (altezze, prezzi, tempi di risposta), ti serve l'istogramma con hist(x).
ggplot2: geom_col contro geom_bar
La versione ggplot2 esiste in due geom, distinti a seconda che il conteggio sia già stato fatto:
library(ggplot2)
# geom_bar(): raw observations in, counting done for you
ggplot(survey, aes(x = response)) +
geom_bar(fill = "steelblue")
# geom_col(): heights already computed, one row per bar
totals <- data.frame(day = c("Mon", "Tue", "Wed", "Thu", "Fri"),
visits = c(42, 51, 47, 60, 78))
ggplot(totals, aes(x = day, y = visits)) +
geom_col(fill = "steelblue")
geom_bar() è table() incorporato nel grafico: prende una riga per osservazione e conta. geom_col() prende dati già aggregati e associa una colonna y all'altezza della barra, l'equivalente del classico barplot(). Dare a geom_bar() dati già contati è la trappola tipica di chi inizia: conta le righe (una ciascuna) e tutte le barre escono alte uguali.
Cosa ti porti a casa
barplot(heights)disegna un vettore con nomi, etable(x)produce esattamente quella forma dai dati di categoria grezzi:barplot(table(x))è l'idioma di base.- Ordina la tabella (o imposta i livelli del factor) prima di disegnare; l'ordine delle barre fa parte del messaggio.
- Una matrice produce barre raggruppate (
beside = TRUE) o impilate (predefinito); aggiungilegend.text = rownames(m). names.arg,col,las = 2ehoriz = TRUEgestiscono le etichette; le barre orizzontali sono le migliori per i nomi lunghi.- Categorie → grafico a barre; classi numeriche → istogramma. In ggplot2: righe grezze →
geom_bar(), altezze calcolate →geom_col().
Prossimo passo: ggplot2 vero e proprio, la grammatica che costruisce tutti questi grafici, e molti altri, con gli stessi pochi pezzi componibili.
Domande frequenti
Come si crea un grafico a barre in R?
Chiama barplot() su un vettore di altezze. Dai dei nomi al vettore, oppure costruiscilo con table(), il cui output ha già i nomi, e ogni elemento diventa una barra con la sua etichetta: barplot(table(df$category)).
Come si crea un barplot raggruppato o impilato in R?
Passa una matrice. Ogni colonna diventa una posizione sull'asse delle categorie; beside = TRUE disegna le righe come barre una accanto all'altra (raggruppate), mentre il valore predefinito beside = FALSE le impila. Aggiungi legend.text = rownames(m) così chi legge può distinguere le righe.
Qual è la differenza tra barplot() e hist() in R?
barplot() confronta categorie distinte: una barra per categoria, barre separate. hist() raggruppa una variabile numerica in intervalli consecutivi: le barre si toccano perché l'asse è una scala continua. Se la tua variabile contiene parole, ti serve barplot(table(x)); se contiene numeri, ti serve hist(x).
Meglio geom_bar o geom_col in ggplot2?
geom_bar() conta al posto tuo: le dai le osservazioni grezze e lei calcola il totale di ogni categoria. geom_col() disegna valori che hai già calcolato: le dai una riga per barra più una colonna con l'altezza. Usare geom_bar() con dati già contati è l'errore classico; in quel caso serve geom_col().