Rosa Oliveira
2015-Jul-08 13:14 UTC
[R] multiple graphs with a single legend and trellis graph
Dear Jim, first of all, thank you very much :) can you please explain me how to use split.screen? I attach my previous graphs and my data, so you can see :) I?m very naive and new in R :( I really tried: library(plotrix) # start a wide plotting device x11(width=10,height=4) y<-runif(100) oldpar<-panes(matrix(1:6,nrow=2,byrow=TRUE),widths=c(1,1,1.7)) par(mar=c(0,2,1.8,0)) mse <- plot(mse.alpha1$lambda[mse.alpha1$nsample==50], mse.alpha1$mse.naive[mse.alpha1$nsample==50], xlab=expression(paste(lambda)),ylab="MSE",type="l",col=4,lty=4, xlim=c(.6,1), ylim=c(0,1), cex.lab=1.5 #,main="yaxs default" ) lines(mse.alpha1$lambda[mse.alpha1$nsample==50],mse.alpha1$mse.RegCal[mse.alpha1$nsample==50],col=2,lty=2) lines(mse.alpha1$lambda[mse.alpha1$nsample==50],mse.alpha1$mse.PL[mse.alpha1$nsample==50],col=3,lty=3) tab.title("alpha 1 N sample=50",tab.col="#88dd88",cex=1) # tab.title("\n\n sample size=50") # problem: when I run: tab.title("Mean squared error for ", paste(alpha[1]))",tab.col="#88dd88",cex=1) # I get an error message: unexpected string constant in "tab.title("Mean squared error for ", paste(alpha[1]))",tab.col="" # I searched but wasn't able to fix this one, neither the other "subtitle": # tab.title("\n\n sample size=50") box() par(mar=c(0,0,1.8,0)) plot(mse.alpha1$lambda[mse.alpha1$nsample==250], mse.alpha1$mse.naive[mse.alpha1$nsample==250], xlab=expression(paste(lambda)),ylab="MSE",type="l",col=4,lty=4, xlim=c(.6,1), ylim=c(0,1), cex.lab=1.5 #,main="yaxs default" ) lines(mse.alpha1$lambda[mse.alpha1$nsample==250],mse.alpha1$mse.RegCal[mse.alpha1$nsample==250],col=2,lty=2) lines(mse.alpha1$lambda[mse.alpha1$nsample==250],mse.alpha1$mse.PL[mse.alpha1$nsample==250],col=3,lty=3) tab.title ( "alpha 1 N sample=250",tab.col="#dd8800",cex=1) box() plot(mse.alpha1$lambda[mse.alpha1$nsample==1000], mse.alpha1$mse.naive[mse.alpha1$nsample== 1000], xlab=expression(paste(lambda)),ylab="MSE",type="l",col=4,lty=4, xlim=c(.6,1), ylim=c(0,1), cex.lab=1.5 #,main="yaxs default" ) lines(mse.alpha1$lambda[mse.alpha1$nsample== 1000],mse.alpha1$mse.RegCal[mse.alpha1$nsample== 1000],col=2,lty=2) lines(mse.alpha1$lambda[mse.alpha1$nsample== 1000],mse.alpha1$mse.PL[mse.alpha1$nsample== 1000],col=3,lty=3) tab.title("alpha 1 N sample=1000",tab.col="#8888dd",cex=1) box() par(mar=c(2,2,1.8,0)) plot(mse.alpha2$lambda[mse.alpha2$nsample==50], mse.alpha2$mse.naive[mse.alpha2$nsample==50], xlab=expression(paste(lambda)),ylab="MSE",type="l",col=4,lty=4, xlim=c(.6,1), ylim=c(0,.17), cex.lab=1.5 #,main="yaxs default" ) lines(mse.alpha2$lambda[mse.alpha2$nsample==50],mse.alpha2$mse.RegCal[mse.alpha2$nsample==50],col=2,lty=2) lines(mse.alpha2$lambda[mse.alpha2$nsample==50],mse.alpha2$mse.PL[mse.alpha2$nsample==50],col=3,lty=3) box() tab.title("alpha 2 N sample=50",tab.col="#aabbcc",cex=1) par(mar=c(2,0,1.8,0)) plot(mse.alpha2$lambda[mse.alpha2$nsample==250], mse.alpha2$mse.naive[mse.alpha2$nsample==250], xlab=expression(paste(lambda)),ylab="MSE",type="l",col=4,lty=4, xlim=c(.6,1), ylim=c(0,.17), cex.lab=1.5 #,main="yaxs default" ) lines(mse.alpha2$lambda[mse.alpha2$nsample==250],mse.alpha2$mse.RegCal[mse.alpha2$nsample==250],col=2,lty=2) lines(mse.alpha2$lambda[mse.alpha2$nsample==250],mse.alpha2$mse.PL[mse.alpha2$nsample==250],col=3,lty=3) box() tab.title("alpha 2 N sample=250",tab.col="#ddbc44",cex=1) # center the title at the middle of the fifth plot mtext("Mean Squared Error",side=1,line=0.8,cex=1.5) par(mar=c(2,0,1.8,12)) plot(mse.alpha2$lambda[mse.alpha2$nsample==1000], mse.alpha2$mse.naive[mse.alpha2$nsample== 1000], xlab=expression(paste(lambda)),ylab="MSE",type="l",col=4,lty=4, xlim=c(.6,1), ylim=c(0,.17), cex.lab=1.5 #,main="yaxs default" ) lines(mse.alpha2$lambda[mse.alpha2$nsample== 1000],mse.alpha2$mse.RegCal[mse.alpha2$nsample==250],col=2,lty=2) lines(mse.alpha2$lambda[mse.alpha2$nsample== 1000],mse.alpha2$mse.PL[mse.alpha2$nsample== 1000],col=3,lty=3) box() tab.title("alpha 2 N sample=1000",tab.col="#ff33cc",cex=1) legend(115,1.8, c("alpha 1 N sample=50","alpha 1 N sample=250","alpha 1 N sample=1000", "alpha 2 N sample=50","alpha 2 N sample=250","alpha 2 N sample=1000"), fill=c("#88dd88","#dd8800","#8888dd","#aabbcc","#ddbc44","#ff33cc"), xpd=NA) legend(115,1.8, c("Naive", "Regression Calibration", "Pseudo Likelihood"), bty = "n",col=c(4,2,3),lty=c(4,2,3), xpd=NA) and I got: Thanks again for your help ;) Atenciosamente, Rosa Oliveira -- ____________________________________________________________________________ Rosa Celeste dos Santos Oliveira, E-mail: rosita21 at gmail.com Tlm: +351 939355143 Linkedin: https://pt.linkedin.com/in/rosacsoliveira ____________________________________________________________________________ "Many admire, few know" Hippocrates> On 08 Jul 2015, at 11:35, Dennis Murphy <djmuser at gmail.com> wrote: > > Hi: > > The general process for doing this kind of thing in either ggplot2 or > lattice is: > > (1) Row concatenate the data frames, assuming they all have the same > structure. It's a good idea to have a number or character string that > identifies each data frame. > (2) After concatenating the data frames, convert the identifier to a factor. > (3) Using ggplot2 or lattice, create the core features of your plot. > In ggplot2, the data frame identifier would be a faceting variable; in > lattice, it would be a conditioning variable in the plot formula: y ~ > x | identifier > > I didn't take the time to look at your code carefully, but it appears > this could be done pretty easily in ggplot2 and probably in lattice as > well. One difference is that it typically takes less code to create a > ggplot2 legend than it does to create one in lattice. > > Here's a reproducible toy example to illustrate how one could do this > in principle with ggplot2. > > DF <- data.frame(id = factor(rep(LETTERS[1:6], each = 10)), > v = factor(sample(1:2, 60, replace = TRUE)), > x = seq_len(10), > y = 0.2 + rep(seq(0.1, 0.6, by = 0.1), each = 10) * > seq_len(10) + rnorm(60)) > > Think of id as the row concatenation of your data frames, where it is > assumed that each data frame has the same variables and the same > structure. The variable v is a manufactured factor to show that you > can make multiple plots and return one legend. The rest is simply fake > data to fit regression lines in each sub-data frame identified with > the same id with different true slopes in each subset but the same > intercept. The code for the plot is > > library(ggplot2) > ggplot(DF, aes(x = x, y = y)) + > geom_point(aes(color = v)) + > geom_smooth(method = "lm", color = "blue", se = FALSE) + > facet_wrap(~ id, ncol = 2) > > The feature of interest in the produced graph is that there are six > panels (produced by the call to facet_wrap()) but only one legend. A > similar graphic in lattice would be > > library(lattice) > xyplot(y ~ x | id, data = DF, type = c("p", "r"), > as.table = TRUE, col = DF$v, > auto.key = list(text = levels(DF$v), > space = "right", > points = TRUE)) > > The problem with the legend in the lattice plot is that the non-red > color in the graph is black but the corresponding color in the legend > is blue. More work is required in lattice to accurately map the > colors, shapes, etc. between the graph and legend. It's not worth > going there at this point. > > In ggplot2, guides (axes or legends) are mappings of aesthetics (in > this case, x, y and color) to variables (x, y and v, respectively). By > default, ggplot2 produces a guide for each mapped aesthetic, which is > defined within the function aes(). > When aes() is used in the ggplot() function, the mappings are global - > i.e., they apply to all subsequent layers produced by a geom or stat > function. When aes() is called inside a geom or stat function, the > mapping is local to the layer produced by the geom/stat call. Wherever > an aesthetic mapping is declared, a guide will be produced unless it > is turned off. With this convention, it is much easier to produce > legend guides in ggplot2 than in lattice. If you want to fine tune the > contents of a legend, there exist functions of the form > scale_<aesthetic>_<type>() that give you more freedom in defining > specific colors, point shapes, etc., as well as labels in the legend. > > Since you did not supply a reproducible example, I would follow steps > (1) and (2) above to arrange your data, and then follow the guidelines > from my fake data example to produce the plot. The trick, especially > with ggplot2, is to figure out how to produce one graph, and then use > faceting to map that structure to all groups. > > From what I can tell, you'll probably need to do some type of melting > operation with reshape2::melt() to stack the three columns Naive, > RegCal and PL, since that is apparently what you want for the legend. > You'll need two faceting variables: nsample and data set identifier. > It appears as though you want to plot points and lines in each panel, > so if you're using ggplot2, you'd use geom_point() and geom_line(). > The titles are not really necessary, as you can produce the > information you need in the strip panels. > > If I read this right, you have: > > * two data sets > * nsample as a faceting/conditioning variable within sample > * lambda as the x-variable > * points and lines for three types of response variables (MSEs) that > are to be compared and labeled in a legend > > If that is correct, I'd suggest the following: > > 1. myDF <- rbind(mse.alpha1, mse.alpha2) # assumes both data frames > have the same variables in the same order > 2. myDF$ID <- factor(rep(c("alpha1", "alpha2"), times > c(nrow(mse.alpha1), nrow(mse.alpha2))) > 3. Melt the three columns to be plotted, something like > > library(reshape2) > myDF.melt <- melt(myDF, id = c("ID", "nsample", "lambda"), measure > c("Naive", "RegCal", "PL")) > > This will return a data frame with 3 * nrow(DF) rows and 5 columns. > The two derived columns are named variable and value, the first of > which returns the variable names as factor levels and the second of > which contains the corresponding values. Then, > > library(ggplot2) > ggplot(myDF.melt, aes(x = lambda, y = value, color = variable)) + > geom_point() + geom_line() + > facet_grid(ID ~ nsample) + > labs(x = expression(lambda), y = "MSE", color = "Type") > > That's the best I can do without access to the data, so you're on your > own to figure this out. If this doesn't work or I misperceived certain > elements of your desired graph (a distinct possibility), then please > re-post a _reproducible example_ back to R-help, which contains both > data and code. You want the example to be minimal so that potential > helpers can quickly see the problem and respond with useful > suggestions. The length of my response in an attempt to divine the > structure of your data punctuates the need for you to provide data + > code + expected outcome. By helping potential helpers to help you, you > are likely to get better and more accurate replies in much less time. > > HTH, > Dennis > > On Tue, Jul 7, 2015 at 2:45 PM, Rosa Oliveira <rosita21 at gmail.com> wrote: >> Iam trying to plot 6 graphs in one single plot and I was able to, nonetheless I wanted that all graphs had just 1 common legend, as the legend is the same for all the 6 graphs and there is no sense in repeating it 6 times and even more, the legends in each graph sometimes don?t fit the graph. >> >> Is there a way to put just one legend for all the 6 graphs ate the same time? >> >> I was told to use a trellis graph, but after days of trying to do that I wasn?t able to. >> >> Can anyone help me? >> >> >> library(ggplot2) >> library(reshape) >> library(lattice) >> >> par(mfrow=c(2,3)) >> mse.alpha1 <-read.csv(file="graphs_mse_alpha1.csv",head=TRUE,sep=",") >> attach(mse.alpha1) >> names(mse1000.alpha1) >> mse.alpha2 <-read.csv(file="graphs_mse_alpha2.csv",head=TRUE,sep=",") >> attach(mse.alpha2) >> names(mse.alpha2) >> nsample==50 >> >> plot(mse.alpha1$lambda[mse.alpha1$nsample==50], >> mse.alpha1$mse.naive[mse.alpha1$nsample==50], >> xlab=expression(paste(lambda)),ylab="MSE",type="l",col=4,lty=4, >> xlim=c(.6,1), ylim=c(0,1), cex.lab=1.5 >> ) >> lines(mse.alpha1$lambda[mse.alpha1$nsample==50],mse.alpha1$mse.RegCal[mse.alpha1$nsample==50],col=2,lty=2) >> lines(mse.alpha1$lambda[mse.alpha1$nsample==50],mse.alpha1$mse.PL[mse.alpha1$nsample==50],col=3,lty=3) >> title ( expression (paste ("Mean squared error for ", alpha[1])), cex.main=1.5) >> title("\n\n sample size=50") >> legend(.7,1, legend= c("Naive", "Regression Calibration", "Pseudo Likelihood"), bty = "n",col=c(4,2,3),lty=c(4,2,3)) >> >> plot(mse.alpha1$lambda[mse.alpha1$nsample==250], >> mse.alpha1$mse.naive[mse.alpha1$nsample==250], >> xlab=expression(paste(lambda)),ylab="MSE",type="l",col=4,lty=4, >> xlim=c(.6,1), ylim=c(0,1), cex.lab=1.5 >> ) >> lines(mse.alpha1$lambda[mse.alpha1$nsample==250],mse.alpha1$mse.RegCal[mse.alpha1$nsample==250],col=2,lty=2) >> lines(mse.alpha1$lambda[mse.alpha1$nsample==250],mse.alpha1$mse.PL[mse.alpha1$nsample==250],col=3,lty=3) >> title ( expression (paste ("Mean squared error for ", alpha[1])), cex.main=1.5) >> title("\n\n sample size=250") >> legend(.7,1, legend= c("Naive", "Regression Calibration", "Pseudo Likelihood"), bty = "n",col=c(4,2,3),lty=c(4,2,3)) >> >> >> plot(mse.alpha1$lambda[mse.alpha1$nsample==1000], >> mse.alpha1$mse.naive[mse.alpha1$nsample== 1000], >> xlab=expression(paste(lambda)),ylab="MSE",type="l",col=4,lty=4, >> xlim=c(.6,1), ylim=c(0,1), cex.lab=1.5 >> ) >> lines(mse.alpha1$lambda[mse.alpha1$nsample== 1000],mse.alpha1$mse.RegCal[mse.alpha1$nsample== 1000],col=2,lty=2) >> lines(mse.alpha1$lambda[mse.alpha1$nsample== 1000],mse.alpha1$mse.PL[mse.alpha1$nsample== 1000],col=3,lty=3) >> title ( expression (paste ("Mean squared error for ", alpha[1])), cex.main=1.5) >> title("\n\n sample size=1000") >> legend(.7,1, legend= c("Naive", "Regression Calibration", "Pseudo Likelihood"), bty = "n",col=c(4,2,3),lty=c(4,2,3)) >> >> plot(mse.alpha2$lambda[mse.alpha2$nsample==50], >> mse.alpha2$mse.naive[mse.alpha2$nsample==50], >> xlab=expression(paste(lambda)),ylab="MSE",type="l",col=4,lty=4, >> xlim=c(.6,1), ylim=c(0,.17), cex.lab=1.5 >> ) >> lines(mse.alpha2$lambda[mse.alpha2$nsample==50],mse.alpha2$mse.RegCal[mse.alpha2$nsample==50],col=2,lty=2) >> lines(mse.alpha2$lambda[mse.alpha2$nsample==50],mse.alpha2$mse.PL[mse.alpha2$nsample==50],col=3,lty=3) >> title ( expression (paste ("Mean squared error for ", alpha[2])), cex.main=1.5) >> title("\n\n sample size=50") >> legend(.7,.17, legend= c("Naive", "Regression Calibration", "Pseudo Likelihood"), bty = "n",col=c(4,2,3),lty=c(4,2,3)) >> >> >> plot(mse.alpha2$lambda[mse.alpha2$nsample==250], >> mse.alpha2$mse.naive[mse.alpha2$nsample==250], >> xlab=expression(paste(lambda)),ylab="MSE",type="l",col=4,lty=4, >> xlim=c(.6,1), ylim=c(0,.17), cex.lab=1.5 >> ) >> lines(mse.alpha2$lambda[mse.alpha2$nsample==250],mse.alpha2$mse.RegCal[mse.alpha2$nsample==250],col=2,lty=2) >> lines(mse.alpha2$lambda[mse.alpha2$nsample==250],mse.alpha2$mse.PL[mse.alpha2$nsample==250],col=3,lty=3) >> title ( expression (paste ("Mean squared error for ", alpha[2])), cex.main=1.5) >> title("\n\n sample size=250") >> legend(.7,.17, legend= c("Naive", "Regression Calibration", "Pseudo Likelihood"), bty = "n",col=c(4,2,3),lty=c(4,2,3)) >> >> plot(mse.alpha2$lambda[mse.alpha2$nsample==1000], >> mse.alpha2$mse.naive[mse.alpha2$nsample== 1000], >> xlab=expression(paste(lambda)),ylab="MSE",type="l",col=4,lty=4, >> xlim=c(.6,1), ylim=c(0,.17), cex.lab=1.5 >> ) >> lines(mse.alpha2$lambda[mse.alpha2$nsample== 1000],mse.alpha2$mse.RegCal[mse.alpha2$nsample==250],col=2,lty=2) >> lines(mse.alpha2$lambda[mse.alpha2$nsample== 1000],mse.alpha2$mse.PL[mse.alpha2$nsample== 1000],col=3,lty=3) >> title ( expression (paste ("Mean squared error for ", alpha[2])), cex.main=1.5) >> title("\n\n sample size=1000") >> legend(.7,.17, legend= c("Naive", "Regression Calibration", "Pseudo Likelihood"), bty = "n",col=c(4,2,3),lty=c(4,2,3)) >> >> >> >> >> >> >> >> >> >> >> Atenciosamente, >> Rosa Oliveira >> >> -- >> ____________________________________________________________________________ >> >> >> Rosa Celeste dos Santos Oliveira, >> >> E-mail: rosita21 at gmail.com >> Tlm: +351 939355143 >> Linkedin: https://pt.linkedin.com/in/rosacsoliveira >> ____________________________________________________________________________ >> "Many admire, few know" >> Hippocrates >> >> ______________________________________________ >> R-help at r-project.org mailing list -- To UNSUBSCRIBE and more, see >> https://stat.ethz.ch/mailman/listinfo/r-help >> PLEASE do read the posting guide http://www.R-project.org/posting-guide.html >> and provide commented, minimal, self-contained, reproducible code.