separate positioning of 2 legends in 1 graph

1,453 views
Skip to first unread message

Martin Kärcher

unread,
Dec 11, 2012, 5:08:04 PM12/11/12
to ggplot2
Dear all,
 
I’m currently trying to position two different legends within one graph. I would like to align them on the left inside the grid area and reduce the vertical space between them. To illustrate my problem I have attached the graph where I added two red rectangles representing where I would like to position the two legends (Figure A.plot18.aim). Does anybody know how to solve this problem? Is there a way to position legends separately? Below I have pasted in the code for the graph including the session info. I have also attached the R-script.
Of course I could also position the two legends horizontally and on top of the graph outside the grid area but in terms of space use this would be somewhat inefficient, which is why I try to avoid it if possible.
 
Many thanks for your help,
 
Martin
 
p.s.: Does anybody know if it is possible to change the size of the legend background?
 
rm(list=ls())
 
library(proto)
library(grid)
library(plyr)
library(reshape)
library(digest)
library(ggplot2)
library(tools)
 
setwd("C:\\Users\\mhk\\Documents\\nur.fueR\\ggsave\\")
 
df.perc.3 <- structure(list(trt = structure(c(1L, 2L, 3L, 1L, 2L, 3L, 1L,
                    2L, 3L, 1L, 2L, 3L, 1L, 2L, 3L, 1L, 2L, 3L, 1L, 2L, 3L, 1L, 2L,
                    3L, 1L, 2L, 3L, 1L, 2L, 3L, 1L, 2L, 3L, 1L, 2L, 3L), class = "factor", .Label = c("0-1",
                    "1-2", "2-3")), resp = c(NA, 92.6096997690531, 79.7921478060046,
                    NA, 98.7080103359173, 94.9181739879414, NA, 97.1326164874552,
                    96.057347670251, NA, 98.4375, 97.94921875, NA, 97.8982300884956,
                    97.8982300884956, NA, NA, NA, NA, 90.686274509804, 90.4411764705882,
                    NA, 97.5510204081633, 93.7414965986395, NA, 88.2820258192651,
                    83.8133068520358, NA, 95.6653225806452, 94.6572580645161, NA,
                    96.5116279069768, 94.670542635659, NA, 98.2581967213115, 97.438524590164
                    ), group = structure(c(2L, 2L, 2L, 1L, 1L, 1L, 2L, 2L, 2L, 1L,
                    1L, 1L, 2L, 2L, 2L, 1L, 1L, 1L, 4L, 4L, 4L, 3L, 3L, 3L, 4L, 4L,
                    4L, 3L, 3L, 3L, 4L, 4L, 4L, 3L, 3L, 3L), .Label = c("carnica EW", "carnica ED",
                    "mellifera EW", "mellifera ED"), class = "factor")), .Names = c("trt", "resp",
                    "group"), row.names = c(NA, -36L), class = "data.frame")
 
df.perc.2b <- structure(list(trt = structure(c(1L, 2L, 3L, 1L, 2L, 3L), class = "factor", .Label = c("0-1", "1-2", "2-3")),
                    resp = c(NA, 94.0193416337148, 90.4454585871723,
                                       NA, 97.865467535666, 95.8563947267053),
                    group = structure(c(2L, 2L, 2L, 1L, 1L, 1L), .Label = c("eggs in worker cells (EW)", "eggs in drone cells (ED)"), class = "factor"),
                    se = c(NA, 1.68994661360938, 2.95728999211006,
                                       NA, 0.549126551165786, 0.824844616926236)),
                    .Names = c("trt", "resp", "group", "se"), row.names = c(NA, -6L), class = "data.frame")
 
df.perc.2a <- structure(list(trt = structure(c(1L, 2L, 3L, 1L, 2L, 3L), class = "factor", .Label = c("0-1", "1-2", "2-3")),
                    resp = c(100, 94.0193416337148, NA,
                                       100, 97.865467535666, NA),
                    group = structure(c(2L, 2L, 2L, 1L, 1L, 1L), .Label = c("eggs in worker cells (EW)", "eggs in drone cells (ED)"), class = "factor"),
                    se = c(NA, NA, NA,
                                       NA, NA, NA)),
                    .Names = c("trt", "resp", "group", "se"), row.names = c(NA, -6L), class = "data.frame")
 
 
ggplot() +
                    geom_line(data = df.perc.2a, aes(y = resp, x = trt, group = group, linetype = group), stat = "identity",
                                       size = 0.5, colour = "black") +
                    geom_smooth(data = df.perc.2b, aes(y = resp, x = trt, group = group, linetype = group, ymax = resp + se,
                                       ymin = resp - se), stat = "identity", size = 0.5, colour = "black") +
                    geom_dotplot(data = na.omit(df.perc.3), aes(y = resp, x = factor(trt), fill = group, colour = group, width = 0.4),
                                       position = "dodge", binaxis = "y", stackdir = "center", dotsize = 1, binwidth = 0.5) +
                    scale_fill_manual(values = c("white", "grey82", "black", "grey40")) +
                    scale_colour_manual(values = rep("black", 4)) +
                    scale_x_discrete(expand = c(0, 0.2), name = "age range of eggs (day)") +
                    scale_y_continuous(expand = c(0.02, 0), breaks = seq(80, 100, 5), name = "eggs remaining (%)") +
                    theme(legend.position = c(0.6, 0.29), legend.background = element_blank(),
                                       legend.key = element_blank(), legend.key.size = unit(c(0.9, 0.9), "lines"),
                                       legend.title = element_blank(), legend.text = element_text(size = 9)) +
                    theme(panel.grid.major = element_line(colour = "white", size = 0.5),
                                       axis.text.x = element_text(size = 9, vjust = 0.9),
                                       axis.text.y = element_text(size = 9, hjust = 0.9),
                                       axis.title.x = element_text(size = 11, vjust = 0.61, hjust = 0.6),
                                       axis.title.y = element_text(size = 11, hjust = 0.555, vjust = 0.59, angle = 90),
                                       plot.margin = unit(c(0.3, 0.3, -0.03, -0.23), "lines")) +
                    guides(group = guide_legend(order = 2), fill = guide_legend(order = 1), colour = guide_legend(order = 1))
 
ggsave("A.plot18.pdf", width = 85/25.4, height = 85/25.4, family = "sans")
 
# legend.background highlighted in red:
 
ggplot() +
                    geom_line(data = df.perc.2a, aes(y = resp, x = trt, group = group, linetype = group), stat = "identity",
                                       size = 0.5, colour = "black") +
                    geom_smooth(data = df.perc.2b, aes(y = resp, x = trt, group = group, linetype = group, ymax = resp + se,
                                       ymin = resp - se), stat = "identity", size = 0.5, colour = "black") +
                    geom_dotplot(data = na.omit(df.perc.3), aes(y = resp, x = factor(trt), fill = group, colour = group, width = 0.4),
                                       position = "dodge", binaxis = "y", stackdir = "center", dotsize = 1, binwidth = 0.5) +
                    scale_fill_manual(values = c("white", "grey82", "black", "grey40")) +
                    scale_colour_manual(values = rep("black", 4)) +
                    scale_x_discrete(expand = c(0, 0.2), name = "age range of eggs (day)") +
                    scale_y_continuous(expand = c(0.02, 0), breaks = seq(80, 100, 5), name = "eggs remaining (%)") +
                    theme(legend.position = c(0.6, 0.29), legend.background = element_rect(colour = "red"),
                                       legend.key = element_blank(), legend.key.size = unit(c(0.9, 0.9), "lines"),
                                       legend.title = element_blank(), legend.text = element_text(size = 9)) +
                    theme(panel.grid.major = element_line(colour = "white", size = 0.5),
                                       axis.text.x = element_text(size = 9, vjust = 0.9),
                                       axis.text.y = element_text(size = 9, hjust = 0.9),
                                       axis.title.x = element_text(size = 11, vjust = 0.61, hjust = 0.6),
                                       axis.title.y = element_text(size = 11, hjust = 0.555, vjust = 0.59, angle = 90),
                                       plot.margin = unit(c(0.3, 0.3, -0.03, -0.23), "lines")) +
                    guides(group = guide_legend(order = 2), fill = guide_legend(order = 1), colour = guide_legend(order = 1))
 
ggsave("A.plot18.red_frames.pdf", width = 85/25.4, height = 85/25.4, family = "sans")
 
# sessionInfo()
 
# R version 2.15.2 (2012-10-26)
# Platform: x86_64-w64-mingw32/x64 (64-bit)
 
# locale:
# [1] LC_COLLATE=German_Austria.1252  LC_CTYPE=German_Austria.1252    LC_MONETARY=German_Austria.1252
# [4] LC_NUMERIC=C                    LC_TIME=German_Austria.1252   
 
# attached base packages:
# [1] tools     grid      stats     graphics  grDevices utils     datasets  methods   base    
 
# other attached packages:
# [1] ggplot2_0.9.2.1 digest_0.5.2    reshape_0.8.4   plyr_1.7.1      proto_0.3-9.2 
 
# loaded via a namespace (and not attached):
#  [1] colorspace_1.2-0   dichromat_1.2-4    gtable_0.1.1       labeling_0.1       MASS_7.3-22      
#  [6] memoise_0.1        munsell_0.4        RColorBrewer_1.0-5 reshape2_1.2.1     scales_0.2.2     
# [11] stringr_0.6.1 
 
A.plot18.aim.pdf
graph_1_two legends

Winston Chang

unread,
Dec 12, 2012, 1:36:55 PM12/12/12
to Martin Kärcher, ggplot2
Hi Martin -

There is a theme option, legend.box.just, which controls the
justification of each legend within the overall legend box. However,
there's a bug in the current version where it isn't possible to
control that value. I've fixed it in the development version of
ggplot2, which you can install using devtools:

# First restart R
install.packages("devtools") # If not already installed
library(devtools)
install_github("ggplot2")
library(ggplot2)
packageVersion('ggplot2') # Should be 0.9.3.99


I've taken your example and simplified it a bit for clarity. In
addition to legend.box.just, look at legend.justification. That
specifies the "anchor point" that is controlled with legend.position.
See here for more information about that:
http://wiki.stdout.org/rcookbook/Graphs/Legends%20(ggplot2)/#changing-the-position-of-the-legend


df.perc.3 <-structure(list(trt = structure(c(1L, 2L, 3L, 1L, 2L, 3L, 1L,
library(ggplot2)
library(grid)
ggplot() +
geom_line(data = df.perc.2a, aes(y = resp, x = trt, group = group,
linetype = group), stat = "identity",
size = 0.5, colour = "black") +
geom_smooth(data = df.perc.2b, aes(y = resp, x = trt, group = group,
linetype = group, ymax = resp + se,
ymin = resp - se), stat = "identity", size = 0.5,
colour = "black") +
geom_dotplot(data = na.omit(df.perc.3), aes(y = resp, x
=factor(trt), fill = group, colour = group, width = 0.4),
position = "dodge", binaxis = "y", stackdir =
"center", dotsize = 1, binwidth = 0.5) +
scale_fill_manual(values = c("white", "grey82", "black", "grey40")) +
scale_colour_manual(values = rep("black", 4)) +
theme(legend.position = c(0, 0),
legend.justification = c(0, 0),
legend.box.just = "left",
legend.background = element_rect(fill=NA, colour="red"),
legend.key = element_blank(),
legend.key.size = unit(c(0.9, 0.9), "lines"),
legend.title = element_blank(),
legend.text = element_text(size = 9)) +
guides(group = guide_legend(order = 2), fill = guide_legend(order =
1), colour = guide_legend(order = 1))



I'm not sure why the legend boxes are so wide, but if you set
colour=NA, it should look OK.

-Winston
legend_just.png

Winston Chang

unread,
Dec 12, 2012, 1:42:25 PM12/12/12
to Martin Kärcher, ggplot2
As for your earlier question about using geom_dotplot... If I
understand you correctly, at each x position, you want to stack across
the different groups. I don't think that it's possible to do that,
though. This is because the stacking with geom_dotplot is done with a
bit of a hack, due to some technical limitations of ggplot2.

I think this code _would_ do what you wanted, if it weren't for the
weird way that stacking is done:

set.seed(909)
dat2 <- data.frame(x=LETTERS[1:3], y=rnorm(90), g=LETTERS[1:2])

# Using dot-density binning
ggplot(dat2, aes(x=x, y=y, fill=g)) + scale_y_continuous(breaks=seq(-4,4,.4)) +
geom_dotplot(binwidth=.2, binaxis="y", stackdir="center", binpositions="all",
stackgroups=TRUE)

# Using histodot binning
ggplot(dat2, aes(x=x, y=y, fill=g)) + scale_y_continuous(breaks=seq(-4,4,.4)) +
geom_dotplot(binwidth=.2, binaxis="y", stackdir="center", method="histodot",
stackgroups=TRUE)


The "stacking" is calculated across all the x positions, which isn't
right for this case. It might be possible to fix it, but it would be
non-trivial.

-Winston
> --
> You received this message because you are subscribed to the ggplot2 mailing
> list.
> Please provide a reproducible example:
> https://github.com/hadley/devtools/wiki/Reproducibility
>
> To post: email ggp...@googlegroups.com
> To unsubscribe: email ggplot2+u...@googlegroups.com
> More options: http://groups.google.com/group/ggplot2
stack_dot_density.png
stack_histodot.png
Reply all
Reply to author
Forward
0 new messages