sabato 27 febbraio 2010

Come creare un InkBlot graph con R

Questo post è dedicato alla creazione con R di un InkBlot chart, anche chiamato Kaleidoscope Chart, di cui potete vedere un esempio a questo link.
Ciò di cui necessitiamo è la library ggplot2, che è il gold standard della grafica con R. E ovviamente dobbiamo procurarci i giusti dati da analizzare!

I dati che utilizzerò sono presi dal sito ISTAT; in particolare userò alcune tabelle con le previsioni della popolazione residente nelle varie regioni italiane, dal 2007 al 2051. Questo è il link da cui ho preso i file csv: LINK.

Per prima cosa importiamo i file csv delle 20 regioni italiane in R:


mydata_piem <- read.table("http://demo.istat.it/uniprev/dati/Residenti-Regione_Piemonte.csv", sep=",")
mydata_vall <- read.table("http://demo.istat.it/uniprev/dati/Residenti-Regione_Valle_D_Aosta.csv", sep=",")
mydata_lomb <- read.table("http://demo.istat.it/uniprev/dati/Residenti-Regione_Lombardia.csv", sep=",")
mydata_trnt <- read.table("http://demo.istat.it/uniprev/dati/Residenti-Regione_Trentino-Alto_Adige.csv", sep=",")
mydata_vene <- read.table("http://demo.istat.it/uniprev/dati/Residenti-Regione_Veneto.csv", sep=",")
mydata_friu <- read.table("http://demo.istat.it/uniprev/dati/Residenti-Regione_Friuli-Venezia_Giulia.csv", sep=",")
mydata_ligu <- read.table("http://demo.istat.it/uniprev/dati/Residenti-Regione_Liguria.csv", sep=",")
mydata_emil <- read.table("http://demo.istat.it/uniprev/dati/Residenti-Regione_Emilia_Romagna.csv", sep=",")
mydata_tosc <- read.table("http://demo.istat.it/uniprev/dati/Residenti-Regione_Toscana.csv", sep=",")
mydata_umbr <- read.table("http://demo.istat.it/uniprev/dati/Residenti-Regione_Umbria.csv", sep=",")
mydata_marc <- read.table("http://demo.istat.it/uniprev/dati/Residenti-Regione_Marche.csv", sep=",")
mydata_lazi <- read.table("http://demo.istat.it/uniprev/dati/Residenti-Regione_Lazio.csv", sep=",")
mydata_abru <- read.table("http://demo.istat.it/uniprev/dati/Residenti-Regione_Abruzzo.csv", sep=",")
mydata_moli <- read.table("http://demo.istat.it/uniprev/dati/Residenti-Regione_Molise.csv", sep=",")
mydata_camp <- read.table("http://demo.istat.it/uniprev/dati/Residenti-Regione_Campania.csv", sep=",")
mydata_pugl <- read.table("http://demo.istat.it/uniprev/dati/Residenti-Regione_Puglia.csv", sep=",")
mydata_basi <- read.table("http://demo.istat.it/uniprev/dati/Residenti-Regione_Basilicata.csv", sep=",")
mydata_cala <- read.table("http://demo.istat.it/uniprev/dati/Residenti-Regione_Calabria.csv", sep=",")
mydata_sici <- read.table("http://demo.istat.it/uniprev/dati/Residenti-Regione_Sicilia.csv", sep=",")
mydata_sard <- read.table("http://demo.istat.it/uniprev/dati/Residenti-Regione_Sardegna.csv", sep=",")


Se andiamo a studiare uno qualsiasi dei dataframe appena creati, ad esempio con il comando mydata_piem[, 1:10], possiamo immediatamente capire quali dati dobbiamo estrarre.
Osservando difatti la struttura del dataframe, deduciamo che:
- le colonne 4, 7, 10, ..., 136 contengono il valore totale della popolazione (maschi + femmine) per ogni anno
- la riga 107 contiene il totale secondo lo "scenario centrale"
- la riga 212 contiene il totale secondo lo "scenario basso"
- la riga 317 contiene il totale secondo lo "scenario alto"
(fa eccezione il file della Valle d'Aosta, in cui vanno estratte le righe 105, 210, 315: forse un errore?).

Supponiamo quindi di voler estrarre l'ammontare della popolazione totale del Piemonte, per tutti gli anni, secondo lo scenario centrale. Usiamo i seguenti comandi:


sequenza <- seq(from=4, to=136, by=3)
aa <- mydata_piem[107, sequenza]


Il vettore sequenza contiene i numeri della colonna che ci servono (a partire dalla quarta, fino alla 136, ogni 3). La riga 107 contiene i totali che ci occorrono. Verifichiamo il formato della variabile appena creata:


class(aa)
[1] "data.frame"


E' un dataframe, ma per il nostro scopo dobbiamo convertirlo in un vettore. Non ho trovato alcun metodo per convertire un dataframe in un vettore, per cui dobbiamo fare qualche operazione in più. Convertire il dataframe in una matrice; estrarre i dati; trasformarli in un vettore contenente dati numerici. Ecco il codice:


aa <- as.matrix(mydata_piem)[107, sequenza]
piemonte <- as.vector(as.numeric(aa1.c))


A questo punto abbiamo ottenuto il vettore piemonte contenente i dati numerici che ci occorrono.

E ora arriva la parte noiosa: dobbiamo ripetere la stessa operazione per tutt'e 20 le regioni italiane, e per i 3 scenari (centrale, basso, alto). Riporto di seguito l'intero codice, indicando con:
- NOME_REGIONE1 = scenario centrale
- NOME_REGIONE2 = scenario basso
- NOME_REGIONE3 = scenario alto


sequenza <- seq(from=4, to=136, by=3)

aa1.c <- as.matrix(mydata_piem)[107, sequenza]
piemonte1 <- as.vector(as.numeric(aa1.c))
aa1.b <- as.matrix(mydata_piem)[212, sequenza]
piemonte2 <- as.vector(as.numeric(aa1.b))
aa1.a <- as.matrix(mydata_piem)[317, sequenza]
piemonte3 <- as.vector(as.numeric(aa1.a))

aa2.c <- as.matrix(mydata_vall)[105, sequenza]
valle_daosta1 <- as.vector(as.numeric(aa2.c))
aa2.b <- as.matrix(mydata_vall)[210, sequenza]
valle_daosta2 <- as.vector(as.numeric(aa2.b))
aa2.a <- as.matrix(mydata_vall)[315, sequenza]
valle_daosta3 <- as.vector(as.numeric(aa2.a))

aa3.c <- as.matrix(mydata_lomb)[107, sequenza]
lombardia1 <- as.vector(as.numeric(aa3.c))
aa3.b <- as.matrix(mydata_lomb)[212, sequenza]
lombardia2 <- as.vector(as.numeric(aa3.b))
aa3.a <- as.matrix(mydata_lomb)[317, sequenza]
lombardia3 <- as.vector(as.numeric(aa3.a))

aa4.c <- as.matrix(mydata_trnt)[107, sequenza]
trentino_alto_adige1 <- as.vector(as.numeric(aa4.c))
aa4.b <- as.matrix(mydata_trnt)[212, sequenza]
trentino_alto_adige2 <- as.vector(as.numeric(aa4.b))
aa4.a <- as.matrix(mydata_trnt)[317, sequenza]
trentino_alto_adige3 <- as.vector(as.numeric(aa4.a))

aa5.c <- as.matrix(mydata_vene)[107, sequenza]
veneto1 <- as.vector(as.numeric(aa5.c))
aa5.b <- as.matrix(mydata_vene)[212, sequenza]
veneto2 <- as.vector(as.numeric(aa5.b))
aa5.a <- as.matrix(mydata_vene)[317, sequenza]
veneto3 <- as.vector(as.numeric(aa5.a))

aa6.c <- as.matrix(mydata_friu)[107, sequenza]
friuli_venezia_giulia1 <- as.vector(as.numeric(aa6.c))
aa6.b <- as.matrix(mydata_friu)[212, sequenza]
friuli_venezia_giulia2 <- as.vector(as.numeric(aa6.b))
aa6.a <- as.matrix(mydata_friu)[317, sequenza]
friuli_venezia_giulia3 <- as.vector(as.numeric(aa6.a))

aa7.c <- as.matrix(mydata_ligu)[107, sequenza]
liguria1 <- as.vector(as.numeric(aa7.c))
aa7.b <- as.matrix(mydata_ligu)[212, sequenza]
liguria2 <- as.vector(as.numeric(aa7.b))
aa7.a <- as.matrix(mydata_ligu)[317, sequenza]
liguria3 <- as.vector(as.numeric(aa7.a))

aa8.c <- as.matrix(mydata_emil)[107, sequenza]
emilia_romagna1 <- as.vector(as.numeric(aa8.c))
aa8.b <- as.matrix(mydata_emil)[212, sequenza]
emilia_romagna2 <- as.vector(as.numeric(aa8.b))
aa8.a <- as.matrix(mydata_emil)[317, sequenza]
emilia_romagna3 <- as.vector(as.numeric(aa8.a))

aa9.c <- as.matrix(mydata_tosc)[107, sequenza]
toscana1 <- as.vector(as.numeric(aa9.c))
aa9.b <- as.matrix(mydata_tosc)[212, sequenza]
toscana2 <- as.vector(as.numeric(aa9.b))
aa9.a <- as.matrix(mydata_tosc)[317, sequenza]
toscana3 <- as.vector(as.numeric(aa9.a))

aa10.c <- as.matrix(mydata_umbr)[107, sequenza]
umbria1 <- as.vector(as.numeric(aa10.c))
aa10.b <- as.matrix(mydata_umbr)[212, sequenza]
umbria2 <- as.vector(as.numeric(aa10.b))
aa10.a <- as.matrix(mydata_umbr)[317, sequenza]
umbria3 <- as.vector(as.numeric(aa10.a))

aa11.c <- as.matrix(mydata_marc)[107, sequenza]
marche1 <- as.vector(as.numeric(aa11.c))
aa11.b <- as.matrix(mydata_marc)[212, sequenza]
marche2 <- as.vector(as.numeric(aa11.b))
aa11.a <- as.matrix(mydata_marc)[317, sequenza]
marche3 <- as.vector(as.numeric(aa11.a))

aa12.c <- as.matrix(mydata_lazi)[107, sequenza]
lazio1 <- as.vector(as.numeric(aa12.c))
aa12.b <- as.matrix(mydata_lazi)[212, sequenza]
lazio2 <- as.vector(as.numeric(aa12.b))
aa12.a <- as.matrix(mydata_lazi)[317, sequenza]
lazio3 <- as.vector(as.numeric(aa12.a))

aa13.c <- as.matrix(mydata_abru)[107, sequenza]
abruzzo1 <- as.vector(as.numeric(aa13.c))
aa13.b <- as.matrix(mydata_abru)[212, sequenza]
abruzzo2 <- as.vector(as.numeric(aa13.b))
aa13.a <- as.matrix(mydata_abru)[317, sequenza]
abruzzo3 <- as.vector(as.numeric(aa13.a))

aa14.c <- as.matrix(mydata_moli)[107, sequenza]
molise1 <- as.vector(as.numeric(aa14.c))
aa14.b <- as.matrix(mydata_moli)[212, sequenza]
molise2 <- as.vector(as.numeric(aa14.b))
aa14.a <- as.matrix(mydata_moli)[317, sequenza]
molise3 <- as.vector(as.numeric(aa14.a))

aa15.c <- as.matrix(mydata_camp)[107, sequenza]
campania1 <- as.vector(as.numeric(aa15.c))
aa15.b <- as.matrix(mydata_camp)[212, sequenza]
campania2 <- as.vector(as.numeric(aa15.b))
aa15.a <- as.matrix(mydata_camp)[317, sequenza]
campania3 <- as.vector(as.numeric(aa15.a))

aa16.c <- as.matrix(mydata_pugl)[107, sequenza]
puglia1 <- as.vector(as.numeric(aa16.c))
aa16.b <- as.matrix(mydata_pugl)[212, sequenza]
puglia2 <- as.vector(as.numeric(aa16.b))
aa16.a <- as.matrix(mydata_pugl)[317, sequenza]
puglia3 <- as.vector(as.numeric(aa16.a))

aa17.c <- as.matrix(mydata_basi)[107, sequenza]
basilicata1 <- as.vector(as.numeric(aa17.c))
aa17.b <- as.matrix(mydata_basi)[212, sequenza]
basilicata2 <- as.vector(as.numeric(aa17.b))
aa17.a <- as.matrix(mydata_basi)[317, sequenza]
basilicata3 <- as.vector(as.numeric(aa17.a))

aa18.c <- as.matrix(mydata_cala)[107, sequenza]
calabria1 <- as.vector(as.numeric(aa18.c))
aa18.b <- as.matrix(mydata_cala)[212, sequenza]
calabria2 <- as.vector(as.numeric(aa18.b))
aa18.a <- as.matrix(mydata_cala)[317, sequenza]
calabria3 <- as.vector(as.numeric(aa18.a))

aa19.c <- as.matrix(mydata_sici)[107, sequenza]
sicilia1 <- as.vector(as.numeric(aa19.c))
aa19.b <- as.matrix(mydata_sici)[212, sequenza]
sicilia2 <- as.vector(as.numeric(aa19.b))
aa19.a <- as.matrix(mydata_sici)[317, sequenza]
sicilia3 <- as.vector(as.numeric(aa19.a))

aa20.c <- as.matrix(mydata_sard)[107, sequenza]
sardegna1 <- as.vector(as.numeric(aa20.c))
aa20.b <- as.matrix(mydata_sard)[212, sequenza]
sardegna2 <- as.vector(as.numeric(aa20.b))
aa20.a <- as.matrix(mydata_sard)[317, sequenza]
sardegna3 <- as.vector(as.numeric(aa20.a))


La parte noiosa è quasi terminata. Creiamo adesso un vettore contenente gli anni, e 3 dataframes contenenti i dati appena ricavati:


anni <- seq(2007, 2051, 1)

mydata.c <- data.frame(piemonte1, valle_daosta1, lombardia1, trentino_alto_adige1, veneto1, friuli_venezia_giulia1, liguria1, emilia_romagna1, toscana1, umbria1, marche1, lazio1, abruzzo1, molise1, campania1, puglia1, basilicata1, calabria1, sicilia1, sardegna1)
mydata.b <- data.frame(piemonte2, valle_daosta2, lombardia2, trentino_alto_adige2, veneto2, friuli_venezia_giulia2, liguria2, emilia_romagna2, toscana2, umbria2, marche2, lazio2, abruzzo2, molise2, campania2, puglia2, basilicata2, calabria2, sicilia2, sardegna2)
mydata.a <- data.frame(piemonte3, valle_daosta3, lombardia3, trentino_alto_adige3, veneto3, friuli_venezia_giulia3, liguria3, emilia_romagna3, toscana3, umbria3, marche3, lazio3, abruzzo3, molise3, campania3, puglia3, basilicata3, calabria3, sicilia3, sardegna3)



Passiamo ora alla parte grafica.
La library ggplot2 ha una sintassi che si discosta moltissimo (a mio parere) dalla sintassi classica di R. E' un mondo a parte, e pertanto preferisco riportare l'esempio svolto, anzichè spiegare sistematicamente tutti i comandi (spiegazione che potrete trovare su altri numerosi siti dedicati esclusivamente a questa library)

Per prima cosa modifichiamo i dataframe creati in modo da renderli leggibili per la funzione ggplot, usando il comando melt:


library(ggplot2)

mydata.c <- melt(mydata.c)
mydata.b <- melt(mydata.b)
mydata.a <- melt(mydata.a)


A questo punto possiamo mettere in grafico direttamente il risultato. Oppure possiamo salvare il grafico in formato .jpg (o altri), scrivendo una apposita funzione, che sfrutta la library ggplot:


save_plot2 <- function(name, width, height){
filename <- paste("name", "jpg", sep = ".")
ggsave(filename, width = width, height = height)
}


Possiamo modificare il formato jpg, e scegliere ad esempio bmp, oppure pdf, o altri.

A questo punto creiamo i grafici, dando loro un nome, in modo da passarli subito dopo alla funzione save_plot2:


gg1 <- ggplot(data=mydata.c, aes(fill=variable)) +
facet_grid(variable~.,space="free", scales="free_y") +
opts(legend.position="none") +
geom_ribbon(aes(x=anni,ymin=-value,ymax=+value))

gg2 <- ggplot(data=mydata.b, aes(fill=variable)) +
facet_grid(variable~.,space="free", scales="free_y") +
opts(legend.position="none") +
geom_ribbon(aes(x=anni,ymin=-value,ymax=+value))

gg3 <- ggplot(data=mydata.a, aes(fill=variable)) +
facet_grid(variable~.,space="free", scales="free_y") +
opts(legend.position="none") +
geom_ribbon(aes(x=anni,ymin=-value,ymax=+value))


Ora possiamo salvare i grafici, scegliendo anche le dimensioni (in pollici: larghezza, altezza):


save_plot2(gg1, 6, 20)
save_plot2(gg2, 6, 20)
save_plot2(gg3, 6, 20)


Il risultato è il seguente:


Nessun commento:

Posta un commento