library(tidyverse) # contiene anche ggplot2
library(janitor)
library(gapminder)
gap_data <- gapminder |>
clean_names() |>
rename(gdp_per_cap = gdp_percap)
gap_2007 <- gap_data |>
filter(year == 2007)Statistical Computing con R
28 ottobre 2026
| Blocco | Contenuto |
|---|---|
| Apertura | da R base alla grammatica dei grafici |
| Attività 1-4 | dati, estetiche, geometrie, layer |
| Debug | i tre errori più comuni |
| Attività 5-8 | position, facet, scale, rifiniture e salvataggio |
| Sfida finale | ricrea questo grafico |
| Chiusura | riepilogo e prossimi passi |
Materiale: questa presentazione, il file lezione_04-ggplot2-esercizi.qmd (su Teams) e i dati dell’esercitazione 1
Ogni concetto segue lo stesso ciclo, ispirato al modello PRIMM (Predict, Run, Investigate, Modify, Make; Sentance, Waite e Kallia, 2019):
gapminderSbagliare l’anticipazione è utile: è il modo più rapido per capire come ragiona ggplot2. I punti Bonus sono per chi finisce prima.
R base: la penna sul foglio
Rispondi prima di eseguire il codice.
Un errore: mapping must be created by aes(), con il suggerimento Did you use %>% or |> instead of +?
La pipe passa il grafico come primo argomento di geom_point(), che invece si aspetta un aes(). Tra i layer serve il +.
Modifica - Scheda, attività 1
Costruisci il grafico a barre del numero di utenti per categoria, con ggplot(), aes() e geom_bar().
|> al posto del +?geom_bar() o geom_col()?Modifica - Scheda, attività 2
Costruisci tab_categoria <- utenti |> tabyl(categoria) e rappresentala con geom_col().
geom_bar() e la stessa aes(x = categoria, y = n)?fct_infreq() o reorder())Di che colore saranno i punti? Ci sarà una legenda?
Modifica - Scheda, attività 3
Rappresenta eta (x) e anno_iscrizione (y) con geom_point() in tre versioni:
geom_point(aes(color = "blue"))geom_point(color = "blue")color = categoria dentro aes()Che cosa dice il messaggio di avvertimento? Bonus: in (c) fissa size = 3 e alpha = 0.6
Removed 5 rows containing missing values: sono i 5 utenti senza anno di nascita. ggplot2 li esclude e lo segnala: è un avvertimento, non un errore.
Le estetiche in ggplot() valgono per tutti i layer, quelle in un geom_ solo per quel layer
Modifica - Scheda, attività 4
Distribuzione dell’eta per categoria: geom_boxplot() + geom_jitter(width = 0.2, alpha = 0.5).
geom_violin() al posto del boxplotModifica - Prima di eseguire, individua l’errore. Poi esegui, leggi il messaggio e correggi.
| Errore | Che cosa succede | |
|---|---|---|
| D1 | geom_bar senza () |
Can’t add geom_bar to a ggplot object. Did you forget to add parentheses? |
| D2 | fill = genere fuori da aes() |
R cerca un oggetto genere nell’ambiente di lavoro: object ‘genere’ not found. Serve aes(fill = genere) |
| D3 | + all’inizio della riga |
la prima riga è già un’istruzione completa (grafico vuoto); la seconda dà errore. Il + va alla fine della riga |
In D2, se nell’ambiente esistesse un oggetto genere, R lo userebbe senza dare errore: un risultato sbagliato è più pericoloso di un errore.
positionModifica - Scheda, attività 5
Con prestiti_validi (prestiti con genere letterario noto) e g <- ggplot(prestiti_validi, aes(x = categoria, fill = genere_letterario)), prova geom_bar() con le tre position.
tabyl() + adorn_*() corrisponde position = "fill"?position = "fill" disegna i profili riga, cioè tabyl(categoria, genere_letterario) |> adorn_percentages("row"): confronta la composizione di gruppi di numerosità molto diversa (139 prestiti degli studenti, 28 dei docenti), ma nasconde quanti sono.
Modifica - Scheda, attività 6
Istogramma dell’eta degli utenti (geom_histogram(binwidth = 5, boundary = 10)) con un pannello per categoria (facet_wrap(~ categoria)).
scales = "free_y"; Bonus 2: facet_grid(genere ~ categoria)Famiglia scale_<estetica>_<tipo>(): scale_x_continuous(), scale_x_log10(), scale_fill_brewer(), scale_color_manual(), scale_color_viridis_d(), …
Modifica - Scheda, attività 7
Con prestiti_mese <- prestiti |> count(biblioteca, mese = month(data_prestito)), costruisci un grafico a linee (geom_line() + geom_point()) dei prestiti per mese, un colore per biblioteca. Aggiungi scale_x_continuous(breaks = 1:12) e scale_color_brewer(palette = "Dark2").
labels = month.abbAd agosto B01, B02 e B03 sono chiuse: count() non crea righe con n = 0 e la linea unisce luglio e settembre
Codice corretto, grafico fuorviante: controlla sempre i dati da cui parte.
Modifica - Scheda, attività 8
Salva in p il grafico dell’attività 7 e aggiungi un pezzo alla volta: labs() (titolo, sottotitolo, assi, legenda, fonte), theme_minimal(), la legenda in basso. Salvalo con ggsave().
theme(legend.position = "bottom") prima di theme_minimal()?p <- p +
labs(title = "Prestiti per mese e biblioteca",
subtitle = "Sistema bibliotecario, 2025",
x = NULL,
y = "Numero di prestiti",
color = "Biblioteca",
caption = "Fonte: esercitazione 1") +
theme_minimal() +
theme(legend.position = "bottom")
ggsave("prestiti_mese_biblioteca.png", p,
width = 8, height = 4.5)Con theme() prima di theme_minimal() la legenda torna a destra: il tema completo annulla le modifiche precedenti.
Modifica - dati utenti
fct_reorder()"#E6A817" e "#003087", trasparenza 0.7utenti |>
filter(!is.na(eta)) |>
ggplot(aes(x = eta, y = fct_reorder(categoria, eta), fill = genere)) +
geom_boxplot(alpha = 0.7) +
scale_fill_manual(values = c("Femmina" = "#E6A817", "Maschio" = "#003087")) +
labs(title = "Età degli utenti per categoria e genere",
subtitle = "Categorie ordinate per età mediana",
x = "Età (anni)", y = NULL, fill = NULL) +
theme_minimal() +
theme(legend.position = "top")filter() prima di ggplot()ggplot(dati, aes(...)) + geom_...()+ tra i layer, |> solo prima di ggplot()geom_bar() conta, geom_col() usa una yaes()) e setting (fuori)position: "stack", "dodge", "fill"facet_wrap() e facet_grid()scale_<estetica>_<tipo>()labs(), theme_...(), poi theme()ggsave()lab_11-grafica-ggplot2 (su Teams), con il codice di esempioNel prossimo compito: i grafici dell’HW05 rifatti con ggplot2
Statistical Computing con R | La logica di ggplot2