Обоснование нескольких легенд в ggmap/ggplot2

Я пытаюсь создать карту с двумя легендами, обозначающими форму и цвет ( "Тип" и "Орг" в примере ниже), а также вставки легенд. Я могу разместить легенды, но я бы хотел, чтобы их оставили оправданными, чтобы их левые края выстроились в линию. Я не могу сделать их чем-то другим, кроме как по отношению друг к другу:

require(ggplot2)
require(ggmap)
require(grid)
require(mapproj)
data <- data.frame(Org=rep(c("ABCDEFG","HIJKLMNOP","QRSTUVWX"),4)
 , Type=rep(c("Y","Z"),6), Lat=runif(12,48,54.5)
 , Long=runif(12,-133.5,-122.5))
osmMap <- get_map(location=c(-134,47.5,-122,55), source = 'osm')
points <- geom_jitter(data=data, aes(Long, Lat, shape=Type
 , colour=Org))
legend <- theme(legend.justification=c(0,0), legend.position=c(0,0)
 , legend.margin=unit(0,"lines"), legend.box="vertical"
 , legend.key.size=unit(1,"lines"), legend.text.align=0
 , legend.title.align=0)
ggmap(osmMap) + points + legend

1 ответ

Эта опция теперь доступна в ggplot2 0.9.3.1, используйте

ggmap(osmMap) + points + legend + theme(legend.box.just = "left")

Старое, ручное решение:

Вот решение:

require(gtable)
require(ggplot2)
require(ggmap)
require(grid)
require(mapproj)
# Original data
data <- data.frame(Org=rep(c("ABCDEFG","HIJKLMNOP","QRSTUVWX"),4),
 Type=rep(c("Y","Z"),6), Lat=runif(12,48,54.5),
 Long=runif(12,-133.5,-122.5))
osmMap <- get_map(location=c(-134,47.5,-122,55), source = 'google')
points <- geom_jitter(data=data, aes(Long, Lat, shape=Type, colour=Org))
legend <- theme(legend.justification=c(0,0), legend.position=c(0,0),
 legend.margin=unit(0,"lines"), legend.box="vertical",
 legend.key.size=unit(1,"lines"), legend.text.align=0,
 legend.title.align=0)
# Data transformation
p <- ggmap(osmMap) + points + legend
data <- ggplot_build(p)
gtable <- ggplot_gtable(data)
# Determining index of legends table
lbox <- which(sapply(gtable$grobs, paste) == "gtable[guide-box]")
# Each legend has several parts, wdth contains total widths for each legend
wdth <- with(gtable$grobs[[lbox]], c(sum(as.vector(grobs[[1]]$widths)), 
 sum(as.vector(grobs[[2]]$widths))))
# Determining narrower legend
id <- which.min(wdth)
# Adding a new empty column of abs(diff(wdth)) mm width on the right of 
# the smaller legend box
gtable$grobs[[lbox]]$grobs[[id]] <- gtable_add_cols(
 gtable$grobs[[lbox]]$grobs[[id]], 
 unit(abs(diff(wdth)), "mm"))
# Plotting
grid.draw(gtable)

Это не зависит от Type или Org. Однако этого было бы недостаточно, имея более двух легенд. Кроме того, если вы внесете некоторые изменения, чтобы изменить список грыз (графических объектов), вам может потребоваться изменить grobs[[8]] на grobs[[i]], где i - это положение ваших легенд, см. gtable$grobs и найдите TableGrob (5 x 3) "guide-box": 2 grobs.

Изменить: 1. Автоматическое определение того, какой grob является таблицей легенд, т.е. не нужно ничего менять после изменения других частей графика. 2. Изменен расчет различий в ширинах, теперь код должен работать, когда есть какие-либо две легенды, то есть в более сложных случаях, например:

licensed under cc by-sa 3.0 with attribution.