ggmap / ggplot2中多个图例的说明 [英] Justification of multiple legends in ggmap/ggplot2

查看:181
本文介绍了ggmap / ggplot2中多个图例的说明的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图用两个表示形状和颜色的传说(下面例子中的Type和Org)制作一张地图,并且插入图例。我可以放置传说,但我希望他们左对齐,使他们的左边缘排队。

  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
,color = 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

解决方案

此选项现在可在ggplot2 0.9.3.1中使用

p>

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

旧的手动解决方案:

是一个解决方案:

  require(gtable)
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 ='google')
points< - geom_jitter data = data,aes(Long,Lat,shape = Type,color = 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)

#数据转换
p <-ggmap(osmMap)+ points + legend
data <-ggplot_build(p)
gtable <-ggplot_gtable(data)

#确定图例索引
lbox< - 其中(sapply(gtable $ grobs,paste)==gtable [guide-box]))
#每个图例有几个部分,wdth包含每个图例的总宽度
wdth < - with(gtable $ grobs [[lbox]],c(sum(as.vector(grobs [[1]] $ widths)),
sum( as.vector(grobs [[2]] $ widths))))
#确定缩小的图例
id< - which.min(wdth)
#添加一个新的空abs (
#)较小的图例框
gtable $ grobs [[lbox]] $ grobs [[id]]< - gtable_add_cols(
gtable $ grobs [[lbox]] $ grobs [[id]],
u nit(abs(diff(wdth)),mm))
#绘制
grid.draw(gtable)

这不取决于类型 Org 。然而,这仅仅具有两个以上的传说是不够的。 另外,如果您做了一些更改以使grobs(图形对象)列表发生更改,您可能需要将 grobs [[8]] 更改为 grobs [[i]] 其中 i 是您的传奇的位置,请参阅 gtable $ grobs 并查找 TableGrob(5 x 3)guide-box:2 grobs



编辑: 1 。自动检测哪个grob是图例表,即在修改绘图的其他部分后不需要改变任何东西。 2.更改了宽度差异的计算,现在代码应该在有任何两个图例时工作,即在更复杂的情况下,例如:


I am trying to make a map with two legends denoting shape and colour ("Type" and "Org" in the example below), and have the legends inset. I can place the legends, but I would like them to be left justified so that their left edges line up. I can't make them anything other than centred with respect to each other:

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

解决方案

This option is now available in ggplot2 0.9.3.1, use

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

Old, manual solution:

Here is a solution:

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)

This does not depend on Type or Org. However, this would not be enough having more than two legends. Also, in case you do some changes so that list of grobs (graphical objects) is altered, you might need to change grobs[[8]] to grobs[[i]] where i is the position of your legends, see gtable$grobs and look for TableGrob (5 x 3) "guide-box": 2 grobs.

Edit: 1. Automatically detecting which grob is legends table, i.e. no need to change anything after modifying other parts of plot. 2. Changed calculation of width differences, now code should work when having any two legends, i.e. in more complex cases as well, for example:

这篇关于ggmap / ggplot2中多个图例的说明的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆