venerdì 13 giugno 2025

Grafici a barre (barplot) con ggplot

grafici a barre (bar plot o barplot) si possono realizzare impiegando le funzioni base di R [1]. Tuttavia con il pacchetto ggplot2 si possono ottenere risultati molto interessanti, qui illustrati con tre script che si aggiungono ad altri già riportati [2] e che, quando si è agli inizi, possono aiutare a familiarizzare con le funzioni di questo pacchetto.

Come trovate riportato nel manuale di riferimento del pacchetto [3] "... Esistono due tipi di grafici a barre: geom_bar() e geom_col() ... geom_bar() rende l'altezza della barra proporzionale al numero di casi in ogni gruppo ... Se volete che le altezze delle barre rappresentino i valori nei dati, usate geom_col() al suo posto".

Oltre al pacchetto ggplot2 [4] dovete accertarvi di avere installato – o dovete scaricare anche – il pacchetto DAAG [5] che contiene il set di dati ais impiegati nell'esempio, il pacchetto RColorBrewer che contiene una serie di palette (raccolte di colori) aggiuntive e il pacchetto gridExtra che consente di combinare i grafici in una sola figura.

Le altezze delle barre rappresentano i valori numerici dei dati

Per questo tipo di rappresentazione si impiega la funzione geom_col().  Copiate e incollate nella Console di R questo script e premete ↵ Invio.

# BARPLOT con ggplot 
# barplot semplici
#
library(ggplot2) # carica il pacchetto per la grafica
library(RColorBrewer) # carica il pacchetto con le palette aggiuntive
library(gridExtra) # carica il pacchetto per combinare i grafici in una sola figura
#
# genera la tabella con i dati da rappresentare
mydata <- data.frame(loc=c("Milano", "Catania", "Roma"), temp=c(18.3, 26.8, 21.2))
#
# barplot di base
plot1 <- ggplot(data=mydata, aes(x=loc, y=temp)) + geom_col()
#
# scambia tra loro gli assi
plot2 <- ggplot(data=mydata, aes(x=loc, y=temp, fill=as.factor(temp))) + geom_col(width=0.6) + ylim(0, 30) + labs(x="Località", y="Temperatura in gradi Celsius") + theme(legend.position="bottom") + scale_fill_discrete(name="°C") + coord_flip()
#
# riporta i valori numerici in testa alle barre
plot3 <- ggplot(data=mydata, aes(x=loc, y=temp)) + geom_col(width=0.6, fill="steelblue3") + ylim(0, 30) + labs(x="Località", y="Temperatura in gradi Celsius") + scale_x_discrete(limits=c("Milano", "Roma", "Catania")) + geom_text(aes(label=temp), vjust=-0.6, color="black", size=3.2)
#
# applica alle barre un gradiente di colori
plot4 <- ggplot(data=mydata, aes(x=loc, y=temp, fill=as.factor(temp))) + geom_col(width=0.6) + ylim(0, 30) + labs(x="Località", y="Temperatura in gradi Celsius") + scale_x_discrete(limits=c("Milano", "Roma", "Catania")) + theme_classic() + scale_fill_brewer(palette="Blues") + labs(fill="°C")
#
# combina i grafici in una sola figura
grid.arrange(plot1, plot2, plot3, plot4, nrow=2, ncol=2)
#

Dopo avere caricato i pacchetti necessari, sono generati i dati impiegati come esempio (mydata):

      loc temp
1  Milano 18.3
2 Catania 26.8
3    Roma 21.2

Per realizzare il primo grafico (plot1) viene impiegata innanzitutto la funzione ggplot()  che inizializza l'oggetto al quale sono collegate con il segno più [+] le successive funzioni, che sviluppano la grafica  che prevede:
→ come primo argomento il nome della tabella che contiene i dati (mydata);
 come secondo argomento la funzione aes() che specifica di riportare in ascisse (x=) la variabile (fattore) loc che indica la località e in ordinate (y=) la variabile (numerica) temp che riporta la temperatura rilevata espressa in gradi Celsius (°C). Alla funzione ggplot() viene quindi collegata con il segno più [+la funzione geom_col() che realizza come detto il grafico a barre nel quale le altezze delle barre rappresentano i valori numerici dei dati.

Questa è la struttura base che rimane identica in tutti e quattro i grafici realizzati, che si differenziano tra loro per le personalizzazioni grafiche via via introdotte.

Il secondo grafico (plot2) aggiunge:
→ la colorazione automatica delle barre con un colore diverso per ogni località (fill=loc);
→ la riduzione dell'ampiezza della barre con width=0.6;
→ la personalizzazione della scala delle ordinate che ora va da 0 a 30;
→ la funzione labs() che specifica le etichette delle ascisse e delle ordinate;
→ la funzione theme() che specifica la posizione in basso ("bottom") per la legenda;
→ il titolo °C della legenda con la funzione scale_fill_discrete();
→ la funzione coord_flip() che scambia tra di loro la posizione degli assi.

Nel terzo grafico (plot3):
→ con fill="steelblue3" viene specificato manualmente il colore delle barre;
→ con scale_x_discrete() viene specificato manualmente l'ordine delle barre;
→ con geom_text() in testa a ciascuna barra viene riportata la temperatura corripondente (temp) specificando posizione (vjust), colore (color) e dimensione (size) dei caratteri.

Il quarto grafico (plot4) ricalca il terzo grafico e in aggiunta:
→ con theme_classic() ripristina la struttura classica impiegata nei grafici;
→ con scale_fill_brewer() applica il gradiente di colori della palette Blues;
→ con labs() riporta nella legenda il titolo °C.

Infine con la funzione grid.arrange() i quattro grafici sono combinati in un'unica figura.


Per vedere come lavorare su dati che contengono un fattore di classificazione copiate e incollate nella Console di R questo secondo script e premete ↵ Invio.

# BARPLOT con ggplot
# barplot con un fattore
library(DAAG) # carica il pacchetto DAAG che include il set di dati ais
library(ggplot2) # carica il pacchetto per la grafica
library(RColorBrewer) # carica il pacchetto con le palette aggiuntive
library(gridExtra) # carica il pacchetto per combinare i grafici in una sola figura
#
# calcola sui dati della tabella ais la mediana di hg per sport 
hgb <- aggregate(hg~sport, data=ais, median) 
hgb # mostra la tabella con i dati da rappresentare
#
# barplot di base
plot1 <- ggplot(data=hgb, aes(x=sport, y=hg)) + geom_col(fill="steelblue3") + ylim(0, 20) + theme(axis.text.x=element_text(angle=90, hjust=1)) 
#
# scambia tra loro gli assi
plot2 <- ggplot(data=hgb, aes(x=sport, y=hg)) + geom_col(width=0.8, fill="steelblue3") + ylim(0, 20) + coord_flip()
#
# riporta i valori numerici all'interno delle barre
plot3 <- ggplot(data=hgb, aes(x=reorder(sport, -hg), y=hg)) + geom_col(width=0.8, fill="steelblue3") + ylim(0, 20) + geom_text(aes(label=hg), vjust=1.6, color="white", size=2.8) + theme(axis.text.x=element_text(angle=90, hjust=1)) + theme(legend.position="none") + labs(title="Mediana dell'emoglobina \n per sport", x="Sport praticato", y="Emoglobina in g/dL")
#
# applica alle barre un gradiente di colori
mycolors <- colorRampPalette(brewer.pal(9, "Blues"))(40)[11:20] # porta da 9 a 40 i colori della palette e seleziona i 10 colori da 11 a 20
plot4 <- ggplot(data=hgb, aes(x=reorder(sport, hg), y=hg, fill=as.factor(hg))) + geom_col(width=0.8) + theme_classic() + ylim(0, 20) + geom_text(aes(label=hg), vjust=-0.6, color="black", size=3.2) + theme(axis.text.x=element_text(angle=90, hjust=1)) + theme(legend.position="none") + labs(title="Mediana dell'emoglobina \n per sport", x="Sport praticato", y="Emoglobina in g/dL") + theme(plot.title=element_text(hjust=0.5)) + scale_fill_manual(values=mycolors)
#
# combina i grafici in una sola figura
grid.arrange(plot1, plot2, plot3, plot4, nrow=2, ncol=2) 
#

Innanzitutto sui dati della tabella ais contenuta nel pacchetto DAAG è calcolata la mediana (median) dell'emoglobina per ciascuno sport (hg~sport), salvandola nella nuova tabella hgb che viene mostrata e che contiene ora i dati da rappresentare:

> hgb # mostra la tabella con i dati da rappresentare
     sport   hg
1   B_Ball 14.0
2    Field 15.5
3      Gym 13.7
4  Netball 12.7
5      Row 14.7
6     Swim 15.1
7   T_400m 14.8
8  T_Sprnt 15.2
9   Tennis 14.3
10  W_Polo 15.6

Nel primo grafico (plot1):
→ sono impiegati i dati della tabella hg riportando in ascisse sport e in ordinate la mediana hg dell'emoglobina;
→ le barre sono colorate tutte con lo stesso colore, specificato in fill;
→ con la funzione ylim() viene dimensionata la scala delle ordinate da 0 a 20;
→ con theme() le etichette dell'asse delle x sono riportate in verticale (angle=90).

Il secondo grafico (plot2) è identico al precedente a parte il fatto che le barre sono ridotte di ampiezza (width=0.8) e gli assi sono scambiati tra loro con coord_flip() per porre le barre in orizzontale.

Il terzo grafico (plot3) riprende nuovamente il primo con alcune aggiunte e modifiche:
→ le barre sono ordinate ponendo la mediana dell'emoglobina in ordine decrescente (-hg);
→ con geom_text() sono riportate all'interno delle barre (vjust=1.6) in colore chiaro (white), rimpiccolendo lievemente i caratteri (size=2.8), le etichette con i valori (label=hg) della mediana dell'emoglobina;
→ con theme() le etichette dell'asse delle x sono riportate in verticale (angle=90);
→ viene esclusa la rappresentazione della legenda ("none");
→ con labs() sono aggiunti il titolo e le etichette degli assi.

Il quarto grafico (plot4) ripresenta il terzo grafico con poche aggiunte e modifiche:
→ innanzitutto sono portati da 9 a 40 i colori della palette, sono selezionati i 10 colori da 11 a 20, e questi sono memorizzati nell'oggetto mycolors;
→ sono riportati colori diversi per ciascun valore dell'emoglobina con as.factor(hg);
→ viene tolto lo sfondo con theme_classic();
→ le etichette con i valori della mediana dell'emoglobina sono portate all'esterno delle barre (vjust=-0.6) aumentando lievemente la dimensione dei caratteri (size=3.2);
→ con hjust=0.5 il titolo viene centrato;
→ le barre sono riportate nel gradiente di colori memorizzati in mycolors.

Questi sono i quattro grafici risultanti.



Vediamo ora cosa accade quando si desidera realizzare i grafici a barre a partire da una tabella che contiene due fattorinei quali come nei due casi precedenti le altezze delle barre rappresentano i valori dei dati e quindi è necessario impiegare la funzione geom_col().

Copiate e incollate nella Console di R questo script e premete ↵ Invio.

# BARPLOT con ggplot 
# barplot con due fattori
library(DAAG) # carica il pacchetto DAAG che include il set di dati ais
library(ggplot2) # carica il pacchetto per la grafica
library(plotrix) # carica il pacchetto per il calcolo dell'errore standard
library(gridExtra) # carica il pacchetto per combinare i grafici in una sola figura
#
# aggrega i dati calcolando media ed errore standard per sport e per sesso
hg <- aggregate(hg~sport+sex, data=ais, FUN=function(x) c(mean=mean(x), se=std.error(x))) 
hg # mostra i dati da rappresentare
media <- hg$hg[,1] # vettore contenente la media
es <- hg$hg[,2] # vettore contenente l'errore standard
#
# grafico a barre impilate per sport e sesso
plot1 <- ggplot(data=hg, aes(x=sport, y=media, fill=sex)) + geom_col() + theme(axis.text.x=element_text(angle=90, hjust=1)) + ylim(0, 31)
#
# grafico a barre affiancate per sport e sesso
plot2 <- ggplot(data=hg, aes(x=sport, y=media, fill=sex)) + geom_col(position=position_dodge()) + theme(axis.text.x=element_text(angle=90, hjust=1)) + ylim(0, 31)
#
plot3 <- ggplot(data=hg, aes(x=sport, y=media, fill=sex)) + geom_col(position=position_dodge()) + theme(axis.text.x=element_text(angle=90, hjust=1)) + ylim(0, 20) + geom_errorbar(aes(ymin=media-1.96*es, ymax=media+1.96*es), width=0.2, position=position_dodge(0.9)) + labs(title="Media dell'emoglobina ± 1.96 es") 
#
plot4 <- ggplot(data=hg, aes(x=sport, y=media, fill=sex)) + geom_point(aes(fill=sex), shape=21, size=3, position=position_dodge(0.9)) + theme_classic() + theme(axis.text.x=element_text(angle=90, hjust=1)) + ylim(0, 20) + geom_errorbar(aes(ymin=media-1.96*es, ymax=media+1.96*es), width=0.2, position=position_dodge(0.9)) + labs(title="Media dell'emoglobina ± 1.96 es", x="Sport praticato", y="Emoglobina in g/dL") + scale_fill_discrete(name = "Sesso", labels = c("Donne", "Uomini"))
#
# combina i grafici in una sola figura
grid.arrange(plot1, plot2, plot3, plot4, nrow=2, ncol=2) 
#

In questo caso dai dati della tabella ais contenuta nel pacchetto DAAG riportiamo la variabile emoglobina suddivisa per sport e per sesso (hg~sport+sex) e ne calcoliamo la media (mean) e l'errore standard (std.error) – quest'ultima funzione richiede il pacchetto plotrix – e questa è la tabella risultante della quale vogliamo rappresentare i grafici a barre:

> hg # mostra i dati da rappresentare
     sport sex    hg.mean      hg.se
1   B_Ball   f 13.1307692  0.2434750
2    Field   f 14.6285714  0.2579353
3      Gym   f 13.6000000  0.4301163
4  Netball   f 12.8173913  0.1182301
5      Row   f 14.0318182  0.1576871
6     Swim   f 13.5666667  0.1943651
7   T_400m   f 13.7727273  0.3122036
8  T_Sprnt   f 14.1750000  0.2780138
9   Tennis   f 13.5285714  0.4144499
10  B_Ball   m 15.1416667  0.2661335
11   Field   m 16.0250000  0.2322893
12     Row   m 15.3866667  0.1835799
13    Swim   m 15.5076923  0.1816807
14  T_400m   m 15.3055556  0.1941080
15 T_Sprnt   m 16.1909091  0.4503442
16  Tennis   m 15.6500000  0.7410578
17  W_Polo   m 15.5176471  0.1741017

Nel primo grafico (plot1) è riportata la struttura base che impieghiamo:
→ sono riportate le barre che rappresentano la media (media) dell'emoglobina con un colore separato per ciascun sesso (fill=sex);
→ con theme() le etichette dell'asse delle x sono riportate in verticale (angle=90); 
→ con la funzione ylim() viene dimensionata la scala delle ordinate da 0 a 31;
→ per tutti gli altri parametri grafici sono lasciati i valori di default per cui abbiamo un grafico a barre impilate che include automaticamente anche una legenda.

Il secondo grafico (plot2) differisce dal precedente solamente per il fatto che, con position=position_dodge(), realizziamo un grafico a barre affiancate.

Nel terzo grafico (plot3):
→ per una miglior visualizzazione viene dimensionata la scala delle ordinate da 0 a 20;
→ con geom_errorbar() si riportano in testa a ciascuna barra, la cui altezza è la media dell'emoglobina, i limiti ±1.96 volte l'errore standard (es) cioè i limiti di confidenza al 95% della media;
→ si aggiunge un titolo.

Il quarto grafico (plot4) ripresenta il precedente ma:
→ sostituisce le barre con un circolo (shape=21) di diametro size=3 posizionato in corrispondenza della media;
→ con theme_classic() toglie lo sfondo;
→ aggiunge agli assi le etichette con una descrizione delle grandezze rappresentate;
→ con scale_fill_discrete() personalizza la legenda.

Questi sono i quattro grafici così realizzati.


Due brevi considerazioni, basate sull'assunto che i grafici possono essere impiegati per fornire una rappresentazione sintetica dei dati, ma che questa non deve mai essere fuorviante:
→ per consentire un confronto dei valori in relazione a un fattore (qui il sesso) è necessario impiegare barre affiancate (in alto a destra), le barre impilate (in alto a sinistra) sono da evitare;
→ è da evitare anche la rappresentazione delle medie sotto forma di barre (in basso a sinistra), in quanto queste danno l'idea di un "continuum" di valori che parte da 0, modi adeguati possono essere (i) la rappresentazione puntiforme qui impiegata (in basso a  destra) o in alternativa anche (ii) un grafico a scatola con i baffi [6].  

Le altezze delle barre rappresentano i conteggi dei dati

Per questo tipo di rappresentazione si impiega la funzione geom_bar() che realizza grafici a barre nei quali le altezze delle barre rappresentano i conteggi dei dati raggruppati mediante uno o più fattori, di volta in volta specificati. Lo facciamo con tre esempi molto semplici.

Nel primo esempio:
→ viene riportato in ascisse (x=sport) lo sport praticato;
→ per ciascuno sport viene riportata con geom_bar() una barra la cui altezza rappresenta il numero di dati (atleti) conteggiati per lo specifico sport;
→ le barre sono riportate in colore grigio con fill="grey";
→ con theme() le etichette dell'asse delle x sono riportate in verticale (angle=90);

# BARPLOT con ggplot (barplot semplice)
library(DAAG) # carica il pacchetto DAAG che include il set di dati ais
library(ggplot2) # carica il pacchetto per la grafica
#
# barplot di base
ggplot(data=ais, aes(x=sport)) + geom_bar(fill="grey") + theme(axis.text.x=element_text(angle=90, hjust=1)) 
#

Il secondo esempio riprende esattamente il primo ma aggiunge con aes(fil=sex) a ciascuna barra colori differenziati in base alla variabile/fattore sesso (sex): in questo modo viene conteggiato il numero di casi (numero di atleti) separatamente per ciascun sesso, lasciando le barre sovrapposte.

# BARPLOT con ggplot 
# barplot sovrapposti, con un fattore
library(DAAG) # carica il pacchetto DAAG che include il set di dati ais
library(ggplot2) # carica il pacchetto per la grafica
#
# barplot sovrapposti differenziati per sesso
ggplot(data=ais, aes(x=sport)) + geom_bar(aes(fill=sex)) + theme(axis.text.x=element_text(angle=90, hjust=1)) 
#

Infine nel terzo esempio, per il resto identico al secondo, aggiungendo position=position_dodge() alla funzione geom_bar() le barre vengono affiancate.

# BARPLOT con ggplot 
# barplot affiancati, con un fattore
library(DAAG) # carica il pacchetto DAAG che include il set di dati ais
library(ggplot2) # carica il pacchetto per la grafica
#
# barplot affiancati differenziati per sesso
ggplot(data=ais, aes(x=sport)) + geom_bar(aes(fill=sex), position=position_dodge()) + theme(axis.text.x=element_text(angle=90, hjust=1)) 
#

I tre grafici ottenuti sono qui riportati affiancati, quello del primo script in alto a sinistra, quello del secondo al centro e quello del terzo a destra.


Potete aggiungere ulteriori approfondimenti consultando gli altri post nei quali il pacchetto ggplot2 è stato impiegato [2] o la sua documentazione ufficiale [4].


---------- 


[2] Fate click su ggplot2 nelle Parole chiave o digitate ggplot2 nella casella Cerca nel blog quindi fate click su Cerca.

[3] "There are two types of bar charts: geom_bar() and geom_col() [and] geom_bar() makes the height of the bar proportional to the number of cases in each group ... If you want the heights of the bars to represent values in the data, use geom_col() instead".

[4] Vedere la documentazione e il manuale di riferimento su:
https://cran.r-project.org/web/packages/ggplot2/index.html

[5] Vedere il post Il set di dati ais nel quale trovate anche come caricare i dati della tabella senza impiegare il pacchetto DAAG

[6] Fate click su grafici a scatola con i baffi nelle Parole chiave.

venerdì 6 giugno 2025

Grafici a linee (line chart) con ggplot

Un grafico a linee (line chart) può essere realizzato, oltre che impiegando le funzioni base di R [1], anche con le funzioni del pacchetto ggplot2 come vediamo ora.

I dati qui utilizzati come esempio sono contenuti nel dataset "Indometh" incluso nella installazione base di R: per vedere gli altri dataset disponibili con questa (ma molti altri sono disponibili nei vari pacchetti aggiuntivi) e che possono essere utili per esercitarsi, digitare

data()

nella Console di R  premere ↵ Invio.

Digitando il nome 

Indometh

del dataset che ci interessa vediamo che contiene la concentrazione (conc) nel siero (espressa in μg/mL cioè in microgrammi per millilitro) del farmaco indometacina (un farmaco antinfiammatorio), misurata secondo la stessa precisa sequenza di ore (time) in sei soggetti (Subject) identificati con i numeri da 1 a 6 :

   Subject time conc
1        1 0.25 1.50
2        1 0.50 0.94
3        1 0.75 0.78
4        1 1.00 0.48
5        1 1.25 0.37
6        1 2.00 0.19
7        1 3.00 0.12
8        1 4.00 0.11
9        1 5.00 0.08
10       1 6.00 0.07
11       1 8.00 0.05
12       2 0.25 2.03
13       2 0.50 1.63
14       2 0.75 0.71
15       2 1.00 0.70
16       2 1.25 0.64
17       2 2.00 0.36
18       2 3.00 0.32
19       2 4.00 0.20
20       2 5.00 0.25
21       2 6.00 0.12
22       2 8.00 0.08
23       3 0.25 2.72
24       3 0.50 1.49
25       3 0.75 1.16
26       3 1.00 0.80
27       3 1.25 0.80
28       3 2.00 0.39
29       3 3.00 0.22
30       3 4.00 0.12
31       3 5.00 0.11
32       3 6.00 0.08
33       3 8.00 0.08
34       4 0.25 1.85
35       4 0.50 1.39
36       4 0.75 1.02
37       4 1.00 0.89
38       4 1.25 0.59
39       4 2.00 0.40
40       4 3.00 0.16
41       4 4.00 0.11
42       4 5.00 0.10
43       4 6.00 0.07
44       4 8.00 0.07
45       5 0.25 2.05
46       5 0.50 1.04
47       5 0.75 0.81
48       5 1.00 0.39
49       5 1.25 0.30
50       5 2.00 0.23
51       5 3.00 0.13
52       5 4.00 0.11
53       5 5.00 0.08
54       5 6.00 0.10
55       5 8.00 0.06
56       6 0.25 2.31
57       6 0.50 1.44
58       6 0.75 1.03
59       6 1.00 0.84
60       6 1.25 0.64
61       6 2.00 0.42
62       6 3.00 0.24
63       6 4.00 0.17
64       6 5.00 0.13
65       6 6.00 0.10
66       6 8.00 0.09

Ai sei soggetti era stata somministrata una identica quantità di indometacina, allo scopo di determinare la velocità alla quale il farmaco viene eliminato: un dato necessario  per stabilire posologia e intervalli di somministrazione.

Ora copiate e incollate nella Console di R questo script e premete ↵ Invio.

# GRAFICO A LINEE con ggplot
#
library(ggplot2) # carica il pacchetto per la grafica
#
# realizza il grafico a linee per ciascuno dei sei soggetti
#
ggplot(data=Indometh, aes(x=time, y=conc, group=Subject, color=Subject, linetype=Subject, shape=Subject)) + geom_line() + geom_point() + theme_classic()
#

Il grafico risultante


viene quindi realizzato:
→ specificando l'origine dei dati (Indometh);
→ riportando in ascisse il tempo (time) e in ordinate la concentrazione (conc); 
→ aggregando i dati per soggetto (group=Subject); 
→ impiegando per ciascun soggetto (Subjectun differente colore (color), linea (linetype) e simbolo (shape);  
→ riportando sul grafico i punti (geom_point) e le linee (geom_line) che li uniscono

Niente di più facile per produrre una versione base del grafico, anche se ovviamente è poi possibile aggiustare a piacere colori, dimensione dei simboli, spessore e tipo delle linee, legenda e quant'altro: esempi si trovano anche in altri post di questo sito [2], ma ovviamente raccomando comunque di scaricare e tenere a portata di mano il manuale di riferimento del pacchetto [3]. Da notare infine che il messaggio che si vede comparire

Messaggio di avvertimento:
Using shapes for an ordinal variable is not advised 

è semplicemente un suggerimento e può essere ignorato.

Ora, visto l'andamento simile delle sei curve di eliminazione del farmaco, l'idea è di realizzare un grafico che riporti per ciascuno dei tempi la media delle concentrazioni rilevate nei sei soggetti e i suoi limiti di confidenza al 95%, rappresentati dalla media +1.96 volte l'errore standard (es) e dalla media -1.96 volte l'errore standard. Per questo copiate e incollate nella Console di R queste righe e premete ↵ Invio.

#
library(plotrix) # carica il pacchetto per il calcolo dell'errore standard
#
# aggrega i dati per ciascun tempo e calcola media ed errore standard della concentrazione per ciascun tempo
#
mydata <- aggregate(conc~time, data=Indometh, FUN=function(x) c(mean=mean(x), se=std.error(x))) 
#
mydata # mostra i dati calcolati
#
media <- mydata$conc[,1] # salva in un vettore le medie calcolate
es <- mydata$conc[,2] # salva in un vettore gli errori standard calcolati
#

Come si vede:
→ serve il pacchetto plotrix, che deve essere preventivamente installato e che fornisce la funzione std.error() per calcolare l'errore standard della media;
→ con la funzione aggregate() sono aggregate le concentrazioni del farmaco rilevate nei sei soggetti a ciascun tempo (conc~time);
→ con FUN=function(x) sono calcolati sui sei valori di concentrazione rilevati a ciascun tempo la media mean(x) e l'errore standard std.err(x);
→ per semplificare e rendere più leggibile il codice successivo media (conc.mean) ed errore standard (conc.se) sono salvati rispettivamente nel vettore media e nel vettore es.

Questi sono i dati calcolati che troviamo in mydata

> mydata # mostra i dati calcolati
   time   conc.mean     conc.se
1  0.25 2.076666667 0.168832593
2  0.50 1.321666667 0.110616957
3  0.75 0.918333333 0.071991512
4  1.00 0.683333333 0.083373324
5  1.25 0.556666667 0.076361712
6  2.00 0.331666667 0.039616214
7  3.00 0.198333333 0.031242777
8  4.00 0.136666667 0.015846486
9  5.00 0.125000000 0.026172505
10 6.00 0.090000000 0.008164966
11 8.00 0.071666667 0.006009252

Dopo questo necessario passo intermedio possiamo di nuovo tornare alla rappresentazione del grafico a linee, copiate e incollate nella Console di R queste ultime righe di codice e premete ↵ Invio.

#
windows() # apre e inizializza una nuova finestra grafica
#
# realizza il grafico a linee riportando per ciascun tempo i limiti di confidenza al 95% della media 
#
ggplot(data=mydata, aes(x=time, y=media)) + geom_line() + geom_point() + theme_classic() + geom_errorbar(aes(ymin=media-1.96*es, ymax=media+1.96*es), width=.1)
#

Dopo avere aperto con windows() una nuova finestra grafica vediamo che la novità rispetto al grafico a linee iniziale, a parte rappresentare in ordinate per ciascun tempo non più i singoli valori di concentrazione bensì la loro media ricavata dalla tabella mydata, è rappresentata dalla funzione geom_errorbar() che con gli argomenti ymin e ymax provvede ad aggiungere al grafico per ciascun tempo i limiti di confidenza al 95% della media, calcolati sottraendo e sommando alla media l'errore standard es moltiplicato per 1.96.

Ed ecco il grafico risultante che, vale la pena di sottolinearlo, fornisce una chiave di lettura cruciale per l'interpretazione dei risultati in quanto di ciascuna media riporta il grado di incertezza. 


Conclusione: anche nel caso assai semplice di un grafico a linee – che come detto può essere realizzato con le funzioni base di R [1], ma sicuramente con maggior difficoltà – il pacchetto ggplot2 fornisce un esempio di versatilità, di rapidità di realizzazione e di ottimi risultati grafici: quanto di meglio per essere invogliati al suo impiego e al suo approfondimento [3]. 


----------

[1] Vedere il post Grafici a linee.

[2] Fate click su ggplot2 nelle Parole chiave o digitate ggplot2 nella casella Cerca nel blog quindi fate click su Cerca.

[3] Vedere il link al manuale di riferimento su:
https://cran.r-project.org/web/packages/ggplot2/index.html