Skip to content

legend for several graphics

7 messages · Georg Otto, John Kane, Gavin Simpson +2 more

#
Hi,

I am trying to generate a figure of 9 plots that are contained in one
device by using

par(mfrow = c(3,3,))

I would like to have 1 common legend for all 9 plots somewhere outside
of the plotting area (as opposed to one legend inside each of the 9
plots, which the function legend() seems to generate by default).

Any hint how to do this?

Best,

Georg
#
?mtitle should do it.
--- Georg Otto <georg.otto at tuebingen.mpg.de> wrote:

            
#
On Wed, 2008-03-05 at 15:28 +0100, Georg Otto wrote:
Here's one way:

op <- par(mfrow = c(3,3), ## split region
          oma = c(5,0,4,0) + 0.1, ## create outer margin
          mar = c(5,4,2,2) + 0.1) ## shrink some margins
plot(1:10, main = "a", pch = 1:2, col= 1:2)
plot(1:10, main = "b", pch = 1:2, col= 1:2)
plot(1:10, main = "c", pch = 1:2, col= 1:2)
plot(1:10, main = "d", pch = 1:2, col= 1:2)
plot(1:10, main = "e", pch = 1:2, col= 1:2)
plot(1:10, main = "f", pch = 1:2, col= 1:2)
plot(1:10, main = "g", pch = 1:2, col= 1:2)
plot(1:10, main = "h", pch = 1:2, col= 1:2)
plot(1:10, main = "i", pch = 1:2, col= 1:2)
## title
mtext("My Plots", side = 3, outer = TRUE, font = 2, line = 1, cex = 1.2)
## draw legend
legend(-12.5, -6, legend = c("Type 1", "Type 2"), pch = 1:2, col = 1:2,
ncol = 2)
par(op)

I had to fiddle by hand with the legend x and y locations to get it
roughly centred. There has to be better way - probably something to do
with reseting the plot region, but I can't recall how to do that now. If
there is, I'm sure someone will tell me what I overlooked.

Is this what you were looking for?

G
#
On Wed, Mar 5, 2008 at 8:28 AM, Georg Otto <georg.otto at tuebingen.mpg.de> wrote:
If you provide more detail about your problem (what are the 9 plots?)
I'm sure we can suggest other solutions using lattice or ggplot that
will substantially simplify your code, as well as automatically
drawing the legend.

Hadley
#
I think you need a par(xpd=NA) before the legend command (At least it
did not show up for me until I set xpd).

For positioning the overall title and legend, one option is the
cnvrt.coords function in the TeachingDemos package.  

To center the overall title over the central column plots (the default
centers it left to right in the window, but with the margins of the
plots this looks a little off): after plotting one of the 3 center
plots, call cnvrt.coords with an x value of 0.5 in plot coordinates
(input='plt') and save the x value of the "tdev" coordinates.  Then use
this value as the at argument to mtext.

To find the values for positioning the legend, give the function the
coordinates in terms of the device (input='tdev', x can either be .5 for
centered or the value computed for mtext above) and store the user
coordinates to pass to legend.

My modification of your example is:

library(TeachingDemos)
op <- par(mfrow = c(3,3), ## split region
          oma = c(5,0,4,0) + 0.1, ## create outer margin
          mar = c(5,4,2,2) + 0.1) ## shrink some margins 
plot(1:10, main = "a", pch = 1:2, col= 1:2) 
plot(1:10, main = "b", pch = 1:2, col= 1:2) 
tmp1 <- cnvrt.coords( 0.5, 0, input='plt' )$tdev # save location for
mtext
plot(1:10, main = "c", pch = 1:2, col= 1:2) 
plot(1:10, main = "d", pch = 1:2, col= 1:2) 
plot(1:10, main = "e", pch = 1:2, col= 1:2) 
plot(1:10, main = "f", pch = 1:2, col= 1:2) 
plot(1:10, main = "g", pch = 1:2, col= 1:2) 
plot(1:10, main = "h", pch = 1:2, col= 1:2) 
plot(1:10, main = "i", pch = 1:2, col= 1:2) 
## title 
mtext("My Plots", side = 3, outer = TRUE, font = 2, line = 1, cex = 1.2,

	at=tmp1$x) 
## draw legend 
par(xpd=NA)
tmp2 <- cnvrt.coords( tmp1$x, 0.05, input='tdev' )$usr # get location
for legend
legend(tmp2$x, tmp2$y, legend = c("Type 1", "Type 2"), 
 	pch = 1:2, col = 1:2, ncol = 2, xjust=0.5, yjust=0.5)
par(op)


Hope this helps,
#
On Thu, 2008-03-06 at 09:41 -0700, Greg Snow wrote:
Hi Greg,

Yes, you are correct. Apologies to the OP, Georg. I must have set xpd =
NA during my tests and not reset it, so when I ran the code without the
par(xpd = FALSE) line, I assumed NA was the default. That was a mistake.

Thanks also for the pointer to cnvrt.coords() - your package keeps being
mentioned for lots of these plotting issues (amongst other topics) on
the list but as yet I have not had chance to take a good look at all it
contains. This is but one more reason to do so.

All the best,

G
#
Thanks a lot, John, Gavin; Hadley and Greg, for your helpful comments
and suggestions. I finally achieved what I wanted using the suggested
method from Gavin with corrections from Greg.

Out of curiosity (and interest to learn): Hadley, how would you
simplify that code using lattice or ggplot and how would you
automatically draw the legend?

Best,

Georg



"Greg Snow" <Greg.Snow at imail.org> writes: