Visualizzare i dati con ggplot2

Uno dei motivi che spingono molte persone che si occupano di analisi dati ad avvicinarsi a R è la sua capacità di generare grafici accattivanti e adatti a ogni esigenza. R possiede tante librerie che permettono di creare visualizzazioni, anche interattive, ma ce n’è una che negli ultimi anni ha preso prepotentemente piede: ggplot2.

Per comprendere l’entità dell’esplosione del fenomeno, possiamo osservare l’andamento temporale delle ricerche su google che utilizzano “ggplot2″ come parola chiave: dal 2009 a oggi (giugno 2013), il trend appare in rapidissima crescita.

Creata nel 2005 da Hadley Wickham, ggplot2 premette di generare dei grafici decisamente più raffinati e attraenti rispetto a quelli che si possono ottenere con il pacchetto grafico contenuto nella distribuzione base di R. La libreria permette di gestire tantissimi parametri in grado di rendere estremamente elegante il risultato finale. La sua logica di funzionamento però non è proprio intuitiva, soprattutto perché è veramente diversa da quella a cui un utente R è comunemente abituato.

La libreria ggplot2 è un’implementazione della cosiddetta “Grammar of Graphics” di Wilkinson. Tale “grammatica” consiste in uno schema generale da applicare alla visualizzazione dei dati, che permette di organizzare un grafico attraverso la combinazione di componenti semantiche distinte, come oggetti geometrici, scale e coordinate.

Fondamentalmente, la funzione da cui si parte per inizializzare un grafico è ggplot. La definizione della tipologia di grafico e i vari parametri saranno definiti successivamente, letteralmente aggiungendo all’oggetto tutte le componenti necessarie. Saranno quindi altre funzioni, come geom_bar, geom_line o geom_point a occuparsi di aggiungere al livello di base barre, linee, punti, e così via. Infine, tramite altre funzioni come xlab, ylab e ggtitle, sarà possibile definire i dettagli più fini.

Descrivere in un unico post tutte le possibilità creative offerte da ggplot2 sarebbe davvero un’impresa ardua. Qui vedremo giusto i rudimenti, in modo da comprendere la filosofia di questa implementazione della “grammatica della grafica”. A titolo eseplificativo utilizzeremo un dataset del Ministero della salute che descrive il numero di posti letto ospedalieri disponibili nel 2011. Da questa pagina è possibile scaricare il dataset, anche se qui lo caricheremo in R direttamente dal web.

beds <- read.csv2("http://www.dati.salute.gov.it/imgs/C_17_dataset_18_download_itemDownload_0_upFile.csv",header=TRUE)
&#91;/code&#93;

<p style="text-align: justify;">Il dataset contiene diverse variabili, ma noi utilizzeremo solo <i>Totale.posti.letto</i> e <i>Tipo.di.Disciplina</i>, che è una variabile di tipo fattore che classifica i posti letto secondo tre categorie: Acuti, Lungodegenza e Riabilitazione. Quello che faremo adesso è costruire un grafico a barre per visualizzare il numero totale di posti letto per ogni tipo di discplina.</p>

<p style="text-align: justify;">Questo è il grafico che arriveremo a costruire:</p>

<img src="http://www.insular.it/wp-content/gallery/post-images/posti_letto.png" width="70%" height="70%" alt="Posti letto">

<p style="text-align: justify;">Per prima cosa, dobbiamo calcolare il numero totale di posti letto per ogni disciplina e inserirli in un nuovo dataset. Questo dataset dovrà contenere anche una variabile che specifica a quale tipo di disciplina fa rifimento ogni valore:</p>

[code language="r"]
df <- data.frame(
    num = tapply(beds$Totale.posti.letto, beds$Tipo.di.Disciplina, sum),
    type = levels(beds$Tipo.di.Disciplina)
)
&#91;/code&#93;

<p style="text-align: justify;">Ora trasformiamo i valori contenuti nella variabile <i>num</i> in percentuali, e salviamoli in una nuova colonna del dataset:</p>

[code language="r"]
df$perc <- 100*(df$num/sum(df$num))
&#91;/code&#93;

<p style="text-align: justify;">Questi valori saranno posizionati in cima a ogni barra, come mostrato nel grafico poco sopra. Arrotondiamoli alla prima cifra decimale e specifichiamo chiaramente che si tratta di percentuali aggiungendo il simbolo "%":</p>

[code language="r"]
df$perc <- round(df$perc,1)
df$perc <- paste(df$perc,"%",sep="")
&#91;/code&#93;

<p style="text-align: justify;">Adesso abbiamo tutto l'occorrente per visualizzare i dati. Il primo passaggio, oltre ad attivare la libreria, consiste nell'inizializzare l'oggetto attraverso la funzione ggplot.</p>

[code language="r"]
library(ggplot2)
gp <- ggplot(df, aes(x=type, y=num, fill=type))
&#91;/code&#93;

<p style="text-align: justify;">La funzione ggplot richiede due argomenti. Il primo è l'oggetto di tipo <i>data.frame</i> che contiene i dati da visualizzare. Il secondo è una particolare lista che viene generata dalla funzione <b>aes</b>, la quale determina l'aspetto (aesthetic) del grafico. La funzione aes richiede necessariamente di specificare "x" e "y", ovvero i nomi delle colonne del dataframe "df", che rappresentano le variabili da porre rispettivamente sugli assi orizzontale e verticale.</p>

<p style="text-align: justify;">Altri argomenti molto utilizzati sono "fill", per specificare quale variabile utilizzare per disporre i colori di riempimento degli oggetti da creare, "group", per specificare un fattore di raggruppamento (necessario negli interaction plot), e "ymin" e "ymax", per determinare i limiti dell'asse verticale.</p>

<p style="text-align: justify;">Ora dobbiamo creare il livello che contiene le barre utilizzando la funzione <b>geom_bar</b>:</p>

[code language="r"]
bar <- geom_bar(stat="identity",show_guide=TRUE)
&#91;/code&#93;

<p style="text-align: justify;">Sono stati esplicitati due parametri: "stat", che specifica quale trasformazione applicare sui dati, e "show_guide", che, se impostato a TRUE, mostrerà a lato una legenda. Noi non abbiamo applicato nessuna trasformazione sui dati (stat="identity") e abbiamo chiesto di mostrare la legenda (in realtà, per default l'argomento è già impostato a TRUE).</p>

<p style="text-align: justify;">A questo punto, i due livelli necessari per la creazione del grafico sono stati creati, e potremmo già concludere qui. Ma ci sono alcune cose che ancora potremmo fare, come aggiungere in cima alle barre delle etichette che specificano i valori percentuali:</p>

[code language="r"]
lab <- geom_text(aes(x=type, y=num, label=perc, vjust=-0.3))
&#91;/code&#93;

<p style="text-align: justify;">Per creare le etichette si utilizza <b>geom_text</b>; ancora, nel codice ritorna la funzione aes. In questo caso, oltre alle coordinate "x" e "y", sono state specificate le etichette ("label") ed è stato impostato un valore di scostamento verticale dalla cima delle barre ("vjust"), per lasciare un po' di spazio tra l'etichetta e la rispettiva barra.</p>

<p style="text-align: justify;">Attraverso le funzioni <b>guides</b> e <b>guide_legend</b> è possibile modificare il titolo della legenda:</p>

[code language="r"]
leg <- guides(fill=guide_legend(title="Posti letto"))
&#91;/code&#93;

<p style="text-align: justify;">Utilizzando <b>xlab</b> e <b>ylab</b>, possiamo creare le etichette da apporre sugli assi orizzontale e verticale:</p>

[code language="r"]
lx <- xlab("Tipo di disciplina")
ly <- ylab("Numero totale")
&#91;/code&#93;

<p style="text-align: justify;">Infine, per creare il grafico, dobbiamo combinare tutti gli oggetti creati in un'unica visualizzazione:</p>

[code language="r"]
gp + bar + lab + lx + ly + leg

Il grafico sarà quindi generato e pronto per essere salvato.

Le possibilità creative offerte da ggplot2 sono veramente tante e tutte molto attraenti. Ma creare un grafico di questo tipo può risultare lungo e piuttosto macchinoso se non si ha una discreta manualità nel gestire la speciale sitassi della libreria. Tendenzialmente, in fase di esplorazione dei dati io preferisco altre soluzioni, più grezze ma immediate; tuttavia, una volta che ho definito esattamente quali grafici presentare, difficilmente ho dubbi su quale libreria scegliere.

Di seguito si riassume tutto il codice utilizzato.


# Preparazione dei dati:
beds <- read.csv2("http://www.dati.salute.gov.it/imgs/C_17_dataset_18_download_itemDownload_0_upFile.csv",header=TRUE) num <- tapply(beds$Totale.posti.letto, beds$Tipo.di.Disciplina, sum) type <- levels(beds$Tipo.di.Disciplina) df <- data.frame(num,type) df$perc <- 100*(df$num/sum(df$num)) df$perc <- round(df$perc,1) df$perc <- paste(df$perc,"%",sep="") # Costruzione del grafico: library(ggplot2) gp <- ggplot(df, aes(x=type, y=num, fill=type)) bar <- geom_bar(stat="identity",show_guide=TRUE) lab <- geom_text(aes(x=type, y=num, label=perc, vjust=-0.3)) leg <- guides(fill=guide_legend(title="Posti letto")) lx <- xlab("Tipo di disciplina") ly <- ylab("Numero totale") gp + bar + lab + lx + ly + leg [/code]

Print Friendly

4 Commenti per “Visualizzare i dati con ggplot2

  1. dark16

    Davide buona sera.
    ho un grosso problema con l’estensione csv.
    Un’agenzia con la quale scambio foto mi chiede un file di metadati in formato csv, mi manda pure un esempio che prevede:
    La Prima riga con il nome della colonna
    la seconda riga con i dati come di seguito:
    oldfilename”,”new_name”,”description”,”keyword”,”country” (questa la prima riga)
    nomefil”,”nuovo”,”era di sera”,”quadro,quaderno,etc”,”IT” (la seconda riga con i dati)

    Quando invio il file salvato in Excel con estensione csv, ho una risposta automatica: “Nessuna riga aggiornata controlla il file”.

    Le ho provate tutte e non capisco più nulla, puoi darmi qualche dritta?

    Grazie

    Dark16

  2. gino

    Ciao ! Ho provato ad utilizzare il tuo codice, ma mi da questo errore: Error in if (is.waive(data) || empty(data)) return(cbind(data, PANEL = integer(0))) :
    missing value where TRUE/FALSE needed
    Come Posso fare?

  3. Davide MassiddaDavide Massidda Autore articolo

    Ciao Oscar, il tuo problema è abbastanza diffuso fra gli utenti R, che talvolta ci si sentono un po’ “soli”; non ti preoccupare: InsulaR esiste anche per questo ;)
    Ti inviterei a riproporre la tua domanda sul forum (www.insular.it/forum) nella sezione “Statistica con R”, così da aprire una discussione nella sezione più adeguata (proverò a risponderti lì).

  4. Oscar

    Ciao, complementi per il sito è bellissimo sia per l’estetica che per i contenuti.

    Sono uno studente di psicologia alle prese con l’anaisi dei dati per la tesi e tutti usano spss, così non posso ricevere aiuto in facoltà. Volevo farvi una semplice domanda:

    Ho un data frame 3fattori x 2scalari(medie condizione pre e post trattamento) devo creare un grafico come questo soltanto che per ogni fattore ho due medie, necessito quindi di raggruppare in funzione dei soggetti le medie per le due condizioni e visualizzare in un unico grafico le medie dei tre fattori.

    Penso non sia questa la sezione giusta e spero potrete perdonarmi! questo è un articolo che spiega perfettamente quello che serve a me quindi ho pensato che commentare qui sotto sarebbe stato piu semplice comprendere cio che vi chiede

    Grazie tante

Lascia un Commento