r - ggplot: "size-robust" way to place horizontal legend at the bottom-right -
i trying place horizontal legend @ bottom-right corner, outside of plotting area.
i realize has been discussed before. however, after long frustrating morning, wasn't able reach "size-robust" solution.
here 3 solutions i've found:
- when set
legend.position
bottom
: legend placed @ bottom-center, yet fail push right side usinglegend.justification
- when set
legend.position
c(1,0)
: legend placed @ bottom-right corner. however, legend placed inside plot. - when add
plot.margin
, pushlegend.position
further down: legend placed @ bottom-right corner , outside of plot. however, when change size of plotting area, legend not correctly positioned more.
incorrect positioning of third solution:
reproducible code:
# generate random data------ sample.n = 50 sample.data = data.frame(x = runif(sample.n,0,1), y = runif(sample.n,0,1), value = runif(sample.n,0,10)) # plot ------ library(ggplot2) # margins fine. , if change size of plotting area, legend bottom- centered # problem: can't push right side ggplot(sample.data, aes(x = x, y = y, color = value)) + geom_point() + theme(legend.direction = "horizontal", legend.position = "bottom") # pushed bottom-right # problem: legend inside plot ggplot(sample.data, aes(x = x, y = y, color = value)) + geom_point() + theme(legend.direction = "horizontal",legend.position = c(1,0)) # problem: inside plot # placed @ bottom-right corner outside plot region # problem: if change size of plotting region, legend not cornred ggplot(sample.data, aes(x = x, y = y, color = value)) + geom_point() + theme(legend.direction = "horizontal", legend.position = c(0.9,-0.2), plot.margin = unit(c(1, 1, 5, 1), "lines"))
theme-legend's documentation:
legend.position position of legends ("none", "left", "right", "bottom", "top", or two-element numeric vector)
legend.justification anchor point positioning legend inside plot ("center" or two-element numeric vector)
edit using 2.2.0, legend can pushed right using legend.justification
, legend.margin
in theme.
# generate random data------ sample.n = 50 sample.data = data.frame(x = runif(sample.n,0,1), y = runif(sample.n,0,1), value = runif(sample.n,0,10)) # plot ------ library(ggplot2) library(gtable) library(grid) p = ggplot(sample.data, aes(x = x, y = y, color = value)) + geom_point() + theme(legend.direction = "horizontal", legend.position = "bottom", legend.box.background = element_rect(colour = "black")) p + theme(legend.justification = "right", legend.margin = margin(t = 2, r = 0, b = 2, l = 2, unit = "mm"))
for worth, leave original answer updated ggplot version 2.2.0.
what have done here extract legend plot, wrap legend in viewport viewport positioned right, put legend plot, , remove original legend.
# generate random data------ sample.n = 50 sample.data = data.frame(x = runif(sample.n,0,1), y = runif(sample.n,0,1), value = runif(sample.n,0,10)) # plot ------ library(ggplot2) library(gtable) library(grid) p = ggplot(sample.data, aes(x = x, y = y, color = value)) + geom_point() + theme(legend.direction = "horizontal", legend.position = "bottom") # ggplot grob g = ggplotgrob(p) # legend index = which(g$layout$name == "guide-box") leg = g$grobs[[index]] # wrap legend in viewport leg$vp = viewport(x = unit(1, "npc"), width = sum(leg$widths), = "right") ### put legend plot # first, current location of legend pos = g$layout[index, ] g = gtable_add_grob(g, leg, t = pos$t, l = pos$l) # remove original legend g$grobs <- g$grobs[-index] g$layout <- g$layout[-index, ] # draw chart grid.newpage() grid.draw(g)
note legend has been moved right, right edge of legend not quite align right edge of plot panel. because legend has internal margin. legend has margin margin set 0 mm. legend align plot panel requires bit more fiddling. in follows, internal margin (and legend margin) set 0. also, legend , internal part of legend wrapped in right justified viewports.
# ggplot grob g = ggplotgrob(p) # legend index = which(g$layout$name == "guide-box") leg = g$grobs[[index]] # remove legend right margin , internal margin leg$widths[4] = unit(0, "mm") leg$grobs[[1]]$widths[5] = unit(0, "mm") # wrap legend in viewport leg$vp = viewport(x = unit(1, "npc"), width = sum(leg$widths), = "right") # wrap internal part of legend in right justified viewport leg$grobs[[1]]$vp = viewport(x = unit(1, "npc"), width = sum(leg$grobs[[1]]$widths), = "right") ### put legend plot # first, current location of legend pos = g$layout[index, ] g = gtable_add_grob(g, leg, t = pos$t, l = pos$l) # remove original legend g$grobs <- g$grobs[-index] g$layout <- g$layout[-index, ] # draw chart grid.newpage() grid.draw(g)
Comments
Post a Comment