00
:
00
:
00
:
00
•Corso SEO AI - Usa SEOEMAIL al checkout per il 30% di sconto

ggplot2 - Grafici Avanzati in R

ggplot2 e’ LA libreria di visualizzazione di R e uno dei pacchetti piu’ influenti dell’intero ecosistema. Creata da Hadley Wickham, ggplot2 si basa sulla ā€œGrammatica dei Graficiā€ (Grammar of Graphics) di Leland Wilkinson, un framework teorico che permette di costruire qualsiasi grafico combinando componenti indipendenti. Ogni grafico in ggplot2 e’ composto da dati, mappature estetiche e geometrie, rendendo il sistema estremamente flessibile e coerente.

Installazione e Caricamento

# Installazione del pacchetto
install.packages("ggplot2")

# Caricamento
library(ggplot2)

# Oppure caricare l'intero tidyverse
library(tidyverse)

La Grammatica dei Grafici

In ggplot2, ogni grafico e’ costruito combinando diversi componenti (layer):

  1. Data: il dataset da visualizzare
  2. Aesthetics (aes): le mappature tra variabili e proprieta’ visive (posizione, colore, forma, dimensione)
  3. Geometries (geom): il tipo di rappresentazione grafica (punti, linee, barre, ecc.)
  4. Facets: la suddivisione in sotto-grafici
  5. Statistics: trasformazioni statistiche dei dati
  6. Coordinates: il sistema di coordinate
  7. Themes: l’aspetto estetico complessivo del grafico

La sintassi segue sempre lo stesso schema: ggplot(data, aes(...)) + geom_*().

# Struttura base di un grafico ggplot2
ggplot(data = mtcars, aes(x = wt, y = mpg)) +
  geom_point()

geom_point() - Scatter Plot

Lo scatter plot e’ il grafico piu’ comune per esplorare relazioni tra due variabili numeriche.

# Scatter plot base
ggplot(mtcars, aes(x = wt, y = mpg)) +
  geom_point()

# Scatter plot con colore per variabile categorica
ggplot(mtcars, aes(x = wt, y = mpg, color = factor(cyl))) +
  geom_point(size = 3) +
  labs(
    title = "Relazione tra Peso e Consumo",
    subtitle = "Dataset mtcars - 32 automobili",
    x = "Peso (1000 lbs)",
    y = "Miglia per Gallone",
    color = "Cilindri"
  )

# Scatter plot con dimensione e forma
ggplot(mtcars, aes(x = wt, y = mpg,
                   color = factor(cyl),
                   size = hp,
                   shape = factor(am))) +
  geom_point(alpha = 0.7) +
  labs(
    title = "Analisi Multidimensionale delle Auto",
    x = "Peso (1000 lbs)",
    y = "MPG",
    color = "Cilindri",
    size = "Cavalli",
    shape = "Cambio"
  ) +
  scale_shape_manual(values = c(16, 17),
                     labels = c("Automatico", "Manuale"))

# Aggiungere una linea di tendenza
ggplot(mtcars, aes(x = wt, y = mpg)) +
  geom_point(color = "steelblue", size = 2) +
  geom_smooth(method = "lm", color = "red", se = TRUE) +
  labs(title = "Regressione Lineare Peso-Consumo",
       x = "Peso", y = "MPG")

geom_line() - Grafici a Linee

geom_line() e’ ideale per dati temporali o serie ordinate.

# Creare dati temporali
set.seed(42)
dati_mensili <- data.frame(
  mese = rep(1:12, 2),
  anno = rep(c("2024", "2025"), each = 12),
  vendite = c(
    round(cumsum(rnorm(12, 5, 2)) + 100),
    round(cumsum(rnorm(12, 7, 2)) + 110)
  )
)

# Grafico a linee con colori per anno
ggplot(dati_mensili, aes(x = mese, y = vendite, color = anno)) +
  geom_line(linewidth = 1.2) +
  geom_point(size = 2) +
  scale_x_continuous(breaks = 1:12, labels = month.abb) +
  labs(
    title = "Andamento Vendite Mensili",
    x = "Mese",
    y = "Vendite (migliaia EUR)",
    color = "Anno"
  ) +
  theme_minimal()

geom_bar() e geom_col() - Grafici a Barre

geom_bar() conta automaticamente le occorrenze, mentre geom_col() usa valori forniti direttamente.

# geom_bar() - conta automaticamente
ggplot(mtcars, aes(x = factor(cyl), fill = factor(cyl))) +
  geom_bar() +
  labs(
    title = "Numero di Auto per Cilindri",
    x = "Cilindri",
    y = "Conteggio",
    fill = "Cilindri"
  ) +
  scale_fill_manual(values = c("steelblue", "darkorange", "darkred")) +
  theme_minimal()

# Barre raggruppate
ggplot(mtcars, aes(x = factor(cyl), fill = factor(am))) +
  geom_bar(position = "dodge") +
  scale_fill_manual(values = c("steelblue", "coral"),
                    labels = c("Automatico", "Manuale")) +
  labs(
    title = "Cilindri per Tipo di Cambio",
    x = "Cilindri",
    y = "Conteggio",
    fill = "Cambio"
  ) +
  theme_minimal()

# Barre impilate con percentuali
ggplot(mtcars, aes(x = factor(cyl), fill = factor(am))) +
  geom_bar(position = "fill") +
  scale_y_continuous(labels = scales::percent) +
  scale_fill_manual(values = c("steelblue", "coral"),
                    labels = c("Automatico", "Manuale")) +
  labs(
    title = "Distribuzione Percentuale Cambio per Cilindri",
    x = "Cilindri",
    y = "Percentuale",
    fill = "Cambio"
  ) +
  theme_minimal()

# geom_col() con valori diretti
dati_barre <- data.frame(
  categoria = c("Prodotto A", "Prodotto B", "Prodotto C", "Prodotto D"),
  valore = c(45, 72, 38, 61)
)

ggplot(dati_barre, aes(x = reorder(categoria, valore), y = valore,
                       fill = categoria)) +
  geom_col() +
  coord_flip() +
  labs(title = "Vendite per Prodotto", x = "", y = "Vendite") +
  theme_minimal() +
  theme(legend.position = "none")

geom_histogram() - Istogrammi

geom_histogram() visualizza la distribuzione di una variabile continua.

# Istogramma base
ggplot(mtcars, aes(x = mpg)) +
  geom_histogram(binwidth = 2, fill = "steelblue",
                 color = "white", alpha = 0.8) +
  labs(
    title = "Distribuzione del Consumo",
    x = "Miglia per Gallone",
    y = "Frequenza"
  ) +
  theme_minimal()

# Istogramma con curva di densita' sovrapposta
ggplot(mtcars, aes(x = mpg)) +
  geom_histogram(aes(y = after_stat(density)),
                 binwidth = 2, fill = "lightblue",
                 color = "darkblue", alpha = 0.7) +
  geom_density(color = "red", linewidth = 1.2) +
  geom_vline(aes(xintercept = mean(mpg)),
             color = "darkgreen", linetype = "dashed", linewidth = 1) +
  labs(
    title = "Distribuzione con Densita' e Media",
    x = "MPG",
    y = "Densita'"
  ) +
  theme_minimal()

# Istogrammi sovrapposti per confronto
ggplot(iris, aes(x = Sepal.Length, fill = Species)) +
  geom_histogram(binwidth = 0.3, alpha = 0.6, position = "identity") +
  labs(
    title = "Distribuzione Lunghezza Sepalo per Specie",
    x = "Lunghezza Sepalo (cm)",
    y = "Frequenza",
    fill = "Specie"
  ) +
  scale_fill_brewer(palette = "Set1") +
  theme_minimal()

geom_boxplot() - Diagrammi a Scatola

geom_boxplot() confronta distribuzioni tra gruppi, evidenziando mediana, quartili e outlier.

# Boxplot per gruppi
ggplot(mtcars, aes(x = factor(cyl), y = mpg, fill = factor(cyl))) +
  geom_boxplot(alpha = 0.7, outlier.color = "red", outlier.size = 3) +
  labs(
    title = "Consumo per Numero di Cilindri",
    x = "Cilindri",
    y = "Miglia per Gallone",
    fill = "Cilindri"
  ) +
  scale_fill_brewer(palette = "Set2") +
  theme_minimal()

# Boxplot con punti sovrapposti (jitter)
ggplot(iris, aes(x = Species, y = Petal.Length, fill = Species)) +
  geom_boxplot(alpha = 0.5) +
  geom_jitter(width = 0.2, alpha = 0.5, size = 1.5) +
  labs(
    title = "Lunghezza Petalo per Specie di Iris",
    x = "Specie",
    y = "Lunghezza Petalo (cm)"
  ) +
  theme_minimal() +
  theme(legend.position = "none")

# Violin plot come alternativa
ggplot(iris, aes(x = Species, y = Sepal.Width, fill = Species)) +
  geom_violin(alpha = 0.6) +
  geom_boxplot(width = 0.1, fill = "white", alpha = 0.8) +
  labs(
    title = "Distribuzione Larghezza Sepalo",
    x = "Specie",
    y = "Larghezza Sepalo (cm)"
  ) +
  scale_fill_brewer(palette = "Pastel1") +
  theme_minimal()

facet_wrap() e facet_grid() - Sotto-Grafici

Le facet permettono di suddividere il grafico in pannelli basati su variabili categoriche.

# facet_wrap: pannelli per una variabile
ggplot(mtcars, aes(x = wt, y = mpg)) +
  geom_point(color = "steelblue", size = 2) +
  geom_smooth(method = "lm", color = "red", se = FALSE) +
  facet_wrap(~ cyl, labeller = labeller(cyl = c(
    "4" = "4 Cilindri", "6" = "6 Cilindri", "8" = "8 Cilindri"
  ))) +
  labs(
    title = "Peso vs Consumo per Numero di Cilindri",
    x = "Peso (1000 lbs)",
    y = "MPG"
  ) +
  theme_minimal()

# facet_grid: griglia per due variabili
ggplot(mtcars, aes(x = hp, y = mpg, color = factor(cyl))) +
  geom_point(size = 2) +
  facet_grid(am ~ gear,
             labeller = labeller(
               am = c("0" = "Automatico", "1" = "Manuale"),
               gear = c("3" = "3 Marce", "4" = "4 Marce", "5" = "5 Marce")
             )) +
  labs(
    title = "Potenza vs Consumo per Cambio e Marce",
    x = "Cavalli (HP)",
    y = "MPG",
    color = "Cilindri"
  ) +
  theme_bw()

# facet_wrap con scale libere
ggplot(iris, aes(x = Sepal.Length, y = Petal.Length)) +
  geom_point(aes(color = Species), size = 2, alpha = 0.7) +
  facet_wrap(~ Species, scales = "free") +
  labs(
    title = "Relazione Sepalo-Petalo per Specie",
    x = "Lunghezza Sepalo",
    y = "Lunghezza Petalo"
  ) +
  theme_minimal() +
  theme(legend.position = "none")

labs() - Etichette e Titoli

labs() controlla tutti i testi del grafico: titolo, sottotitolo, didascalia e etichette degli assi.

ggplot(mtcars, aes(x = wt, y = mpg, color = factor(cyl))) +
  geom_point(size = 3) +
  labs(
    title = "Analisi del Consumo delle Automobili",
    subtitle = "Relazione tra peso e consumo di carburante",
    caption = "Fonte: dataset mtcars (1974 Motor Trend US)",
    x = "Peso del Veicolo (migliaia di libbre)",
    y = "Consumo (miglia per gallone)",
    color = "Numero\nCilindri",
    tag = "Fig. 1"
  )

theme() - Personalizzare l’Aspetto

theme() permette di controllare ogni aspetto visivo del grafico che non riguarda i dati.

# Temi predefiniti
p <- ggplot(mtcars, aes(x = wt, y = mpg, color = factor(cyl))) +
  geom_point(size = 3) +
  labs(title = "Peso vs Consumo", x = "Peso", y = "MPG", color = "Cilindri")

# Tema minimale
p + theme_minimal()

# Tema classico
p + theme_classic()

# Tema scuro
p + theme_dark()

# Tema bianco e nero
p + theme_bw()

# Personalizzazione avanzata del tema
ggplot(mtcars, aes(x = wt, y = mpg, color = factor(cyl))) +
  geom_point(size = 3) +
  labs(title = "Grafico Personalizzato", x = "Peso", y = "MPG",
       color = "Cilindri") +
  theme_minimal() +
  theme(
    plot.title = element_text(size = 16, face = "bold", hjust = 0.5),
    axis.title = element_text(size = 12, face = "italic"),
    axis.text = element_text(size = 10),
    legend.position = "bottom",
    legend.title = element_text(face = "bold"),
    panel.grid.minor = element_blank(),
    panel.border = element_rect(color = "gray50", fill = NA)
  )

scale_* - Personalizzare le Scale

Le funzioni scale_* controllano la mappatura tra dati e proprieta’ estetiche.

# Colori personalizzati
ggplot(mtcars, aes(x = wt, y = mpg, color = factor(cyl))) +
  geom_point(size = 3) +
  scale_color_manual(
    values = c("4" = "#2196F3", "6" = "#FF9800", "8" = "#F44336"),
    labels = c("4 cilindri", "6 cilindri", "8 cilindri")
  ) +
  labs(title = "Colori Personalizzati", color = "Motore") +
  theme_minimal()

# Palette di colori predefinite
ggplot(iris, aes(x = Sepal.Length, y = Petal.Length, color = Species)) +
  geom_point(size = 2) +
  scale_color_brewer(palette = "Dark2") +
  theme_minimal()

# Scala colore continua con gradiente
ggplot(mtcars, aes(x = wt, y = mpg, color = hp)) +
  geom_point(size = 3) +
  scale_color_gradient(low = "yellow", high = "red") +
  labs(title = "Gradiente di Colore per Potenza",
       color = "Cavalli (HP)") +
  theme_minimal()

# Personalizzare gli assi
ggplot(mtcars, aes(x = wt, y = mpg)) +
  geom_point(color = "steelblue", size = 2) +
  scale_x_continuous(breaks = seq(1, 6, 0.5),
                     limits = c(1, 6)) +
  scale_y_continuous(breaks = seq(10, 35, 5),
                     limits = c(10, 35)) +
  theme_minimal()

ggsave() - Salvare i Grafici

ggsave() salva l’ultimo grafico generato in un file con dimensioni e risoluzione specificate.

# Creare un grafico
p <- ggplot(iris, aes(x = Sepal.Length, y = Petal.Length,
                      color = Species)) +
  geom_point(size = 2, alpha = 0.7) +
  geom_smooth(method = "lm", se = FALSE) +
  labs(title = "Relazione Sepalo-Petalo nel Dataset Iris",
       x = "Lunghezza Sepalo (cm)",
       y = "Lunghezza Petalo (cm)") +
  theme_minimal()

# Salvare come PNG
ggsave("grafico_iris.png", plot = p, width = 10, height = 6, dpi = 300)

# Salvare come PDF
ggsave("grafico_iris.pdf", plot = p, width = 10, height = 6)

# Salvare come SVG (vettoriale)
ggsave("grafico_iris.svg", plot = p, width = 10, height = 6)

Esempio Completo: Analisi Visiva del Dataset Iris

Ecco un esempio che combina diverse funzionalita’ di ggplot2 per creare un’analisi visiva completa.

library(ggplot2)
library(dplyr)

# 1. Scatter plot con regressione per specie
p1 <- ggplot(iris, aes(x = Sepal.Length, y = Petal.Length,
                        color = Species, shape = Species)) +
  geom_point(size = 2.5, alpha = 0.7) +
  geom_smooth(method = "lm", se = TRUE, alpha = 0.2) +
  scale_color_brewer(palette = "Set1") +
  labs(title = "Correlazione Sepalo-Petalo",
       x = "Lunghezza Sepalo (cm)", y = "Lunghezza Petalo (cm)") +
  theme_minimal() +
  theme(legend.position = "bottom")

# 2. Boxplot comparativo
p2 <- ggplot(iris, aes(x = Species, y = Sepal.Width, fill = Species)) +
  geom_boxplot(alpha = 0.6) +
  geom_jitter(width = 0.15, alpha = 0.4, size = 1) +
  scale_fill_brewer(palette = "Pastel1") +
  labs(title = "Distribuzione Larghezza Sepalo",
       x = "Specie", y = "Larghezza (cm)") +
  theme_minimal() +
  theme(legend.position = "none")

# 3. Istogramma con facet
p3 <- ggplot(iris, aes(x = Petal.Width, fill = Species)) +
  geom_histogram(binwidth = 0.2, color = "white", alpha = 0.8) +
  facet_wrap(~ Species, ncol = 1) +
  scale_fill_brewer(palette = "Set2") +
  labs(title = "Distribuzione Larghezza Petalo per Specie",
       x = "Larghezza Petalo (cm)", y = "Frequenza") +
  theme_minimal() +
  theme(legend.position = "none")

# Per combinare i grafici si puo' usare il pacchetto patchwork
# install.packages("patchwork")
# library(patchwork)
# p1 / (p2 | p3)

# Oppure stamparli singolarmente
print(p1)
print(p2)
print(p3)

Conclusione

ggplot2 e’ il sistema di visualizzazione piu’ completo e flessibile disponibile in R. La sua architettura basata sulla grammatica dei grafici permette di costruire qualsiasi visualizzazione componendo layer indipendenti: dati con ggplot(), mappature con aes(), geometrie con geom_*(), sotto-grafici con facet_wrap() e facet_grid(), personalizzazione con labs(), theme() e scale_*(), e salvataggio con ggsave(). Padroneggiare ggplot2 significa poter trasformare qualsiasi dataset in visualizzazioni chiare, informative e di qualita’ professionale, pronte per report, presentazioni e pubblicazioni scientifiche.