Risolvere pRoblemi

Risolvere problemi è il metodo migliore per imparare qualcosa. Ricordate la scuola?

Con la programmazione in R è un po’ la stessa cosa. Risolvere problemi favorisce la dimestichezza con il programma e facilita l’apprendimento nell’uso dei vari pacchetti. Il suggerimento è di iniziare da cose semplici, come quelle che potete trovare in un manuale o nei siti di discussione.

Di recente l’utente Umesh Acharya ha postato un quesito su CrossValidated, un sito che si occupa di problemi di statistica. Il quesito in realtà è di natura informatica, poiché riguarda la codifica di un plot. Fino a poco tempo fa, il quesito era reperibile qui, ma è stato ormai rimosso, essendo quel genere di domande più adatte a StackOverflow, il sito gemello di CrossValidated, ma più genericamente dedicato a problemi informatici.

Domanda Umesh: “Come posso mettere tre plot in un’unica finestra?”. La domanda non è banale. Umesh ha creato una funzione che consente di “stampare” nel plot la formula di una regressione usando i valori stimati per i parametri, e per farlo ha usato ggplot2, il programma di grafica creato da Hadley Wickham, mago della programmazione in R (su InsulaR se n’era già parlato qui).

A differenza del sistema grafico base, in ggplot2 non è possibile ripartire le finestre grafiche con il comando par (che avete visto usare in precedenti post). Bisogna agire sulle griglie. E bisogna saperlo.

Dunque, abbiamo un dataset con 6 variabili, che vogliamo rappresentare a coppie di due, coordinate in una regressione. Come si rappresentano i tre grafici in un’unica finestra? Iniziamo a costruire il nostro dataset, che chiameremo ‘tom’ (toy object model):

a1 <- seq(from=1, to=10, by=1)
a2 <- seq (from=2, to=20, by=2)
b1 <- seq(from=3, to=30, by=3)
b2 <- seq(from=4, to=40, by=4)
c1 <- seq(from=5, to=50, by=5)
c2 <- seq(from=2, to=29, by=3)

# combiniamo i vettori in una matrice con il comando cbind
dataframe <- cbind(a1,a2,b1,b2,c1,c2)

# trasformiamo la matrice in un dataframe con etichette per l’intestazione delle variabili
tom <- as.data.frame(dataframe)

E adesso la bella funzione creata dal nostro Umesh per inserire il risultato della regressione nel grafico:

## function to create equation expression
lm_eqn = function(x, y, df){
    m <- lm(y ~ x, df);
    eq <- substitute(italic(y) == b %.% italic(x) + a,
    list(a = format(coef(m)[1], digits = 2),
    b = format(coef(m)[2], digits = 2)))
    as.character(as.expression(eq));
}

Chiamiamo il pacchetto:

library (ggplot2)

Creiamo i tre grafici in ggplot2:

################ a1 and a2 couple of variables
P1<-ggplot(tom, aes(x=a1, y=a2)) +
geom_point(shape=1) +      # Use hollow circles

geom_smooth(method=lm,    # Add linear regression line

se=FALSE)     # Don't add shaded confidence region

P2<- P1 + labs (x= "a1 value", y = "a2 value")## add x and y labels

P3 <- P2 + theme(axis.title.x = element_text(face="bold", size=20)) +
labs(x="a1 value")                            #label and change font size

P4 <- P3 + scale_x_continuous("a1 value",
limits=c(-10,60),
breaks=seq(-10, 60, 10))  ##adjust axis limits and breaks

##add regression equation using annotate
P5a <- P4 + annotate("text", x = 30, y = 10, label = lm_eqn(tom$a1, tom$a2, tom), color="black", size = 5, parse=TRUE)

P5a

Variabili a1 e a2

################ b1 and b2 couple of variables
P1b<-ggplot(tom, aes(x=b1, y=b2)) +
geom_point(shape=1) +      # Use hollow circles
geom_smooth(method=lm,    # Add linear regression line
se=FALSE)     # Don't add shaded confidence region

P2b<- P1b + labs (x= "b1 value", y = "b2 value")## add x and y labels

P3b <- P2b + theme(axis.title.x = element_text(face="bold", size=20)) +
labs(x="b1 value")                            #label and change font size
P4b <- P3b + scale_x_continuous("b1 value",
limits=c(-10,60),
breaks=seq(-10, 60, 10))  ##adjust axis limits and breaks

##add regression equation using annotate
P5b <- P4b + annotate("text", x = 40, y = 20, label = lm_eqn(tom$b1, tom$b2, tom), color="black", size = 5, parse=TRUE)

P5b

Variabili b1 e b2

################ c1 and c2 couple of variables
P1c<-ggplot(tom, aes(x=c1, y=c2)) +
geom_point(shape=1) +      # Use hollow circles
geom_smooth(method=lm,    # Add linear regression line
se=FALSE)     # Don't add shaded confidence region

P2c<- P1c + labs (x= "c1 value", y = "c2 value")## add x and y labels

P3c <- P2c + theme(axis.title.x = element_text(face="bold", size=20)) +
labs(x="c1 value")                            #label and change font size

P4c <- P3c + scale_x_continuous("c1 value",
limits=c(-10,60),
breaks=seq(-10, 60, 10))  ##adjust axis limits and breaks

##add regression equation using annotate
P5c <- P4c + annotate("text", x = 40, y = 15, label = lm_eqn(tom$c1, tom$c2, tom), color="black", size = 5, parse=TRUE)

P5c

Variabili c1 e c2

E adesso il gran finale. Come rappresentare i tre grafici in un’unica finestra?

Se il nostro Umesh, peraltro bravo programmatore, fosse stato meno pigro, avrebbe scoperto subito che CrossValidated non era il sito che faceva per lui, e avrebbe scoperto in fretta almeno due soluzioni al suo problema.

Le soluzioni che qui propongo sono tratte dal sito Cookbook for R, curato da Wiston Chang, una autentica miniera di gemme.

La prima soluzione utilizza il sistema di gestione delle griglie, e fa uso di due librerie aggiuntive a ggplot2 (librerie che dovrete scaricare se volete usarle).

library(grid)
library(gridExtra)

# semplice ed elegante (il titolo lo scegliete voi)
grid.arrange(P5a, P5b, P5c, ncol = 3, main = "Your main title")
# after saving, dev.off()
# se volete cambiare le dimensioni del titolo, seguite le istruzioni

### changing dimensions of the title
grid.arrange(P5a, P5b, P5c, ncol = 3,
main=textGrob("Your main title", gp=gpar(fontsize=20,font=3)))

Combinazione grafici

La seconda soluzione fa ricorso ad una funzione creata da Chang, e messa cortesemente a disposizione degli utenti dal creatore (il risultato è analogo a quello riportato sopra).


# Multiple plot function
# ggplot objects can be passed in …, or to plotlist (as a list of ggplot objects)
# – cols: Number of columns in layout
# – layout: A matrix specifying the layout. If present, ‘cols’ is ignored.
# If the layout is something like matrix(c(1,2,3,3), nrow=2, byrow=TRUE),
# then plot 1 will go in the upper left, 2 will go in the upper right, and
# 3 will go all the way across the bottom.
# from: http://www.cookbook-r.com/

multiplot <- function(..., plotlist=NULL, file, cols=1, layout=NULL) { require(grid) # Make a list from the ... arguments and plotlist plots <- c(list(...), plotlist) numPlots = length(plots) # If layout is NULL, then use 'cols' to determine layout if (is.null(layout)) { # Make the panel # ncol: Number of columns of plots # nrow: Number of rows needed, calculated from # of cols layout <- matrix(seq(1, cols * ceiling(numPlots/cols)), ncol = cols, nrow = ceiling(numPlots/cols)) } if (numPlots==1) { print(plots[[1]]) } else { # Set up the page grid.newpage() pushViewport(viewport(layout = grid.layout(nrow(layout), ncol(layout)))) # Make each plot, in the correct location for (i in 1:numPlots) { # Get the i,j matrix positions of the regions that contain this subplot matchidx <- as.data.frame(which(layout == i, arr.ind = TRUE)) print(plots[[i]], vp = viewport(layout.pos.row = matchidx$row, layout.pos.col = matchidx$col)) } } } # Una volta che avete caricata la funzione nell’area di lavoro, l’uso è semplicissimo # (Il numero di colonne (in questo caso 3, ma può variare a piacimento): multiplot(P5a, P5b, P5c, cols=3) [/code] That's all, folks! Antonello Preti Stay Tuned for our next episode!

Print Friendly, PDF & Email
Print Friendly, PDF & Email