Подтвердить что ты не робот

Обоснование нескольких легенд в 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

enter image description here

4b9b3361

Ответ 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. enter image description here

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

enter image description here