仅用一个普通图例绘制 class tmap 的多个对象

Draw multiple object of class tmap with just one common legend

我正在尝试使用网格包中的 grid.layout() 在一页中使用 tm_shape() 和 tm_layout() 从 tmap 包中绘制多张地图。我只想为所有地图绘制一个通用图例,类似于此处显示的示例:

ggplot separate legend and plot

不幸的是,tmap 不提供 ggplot 对象。有人知道如何对 tmap 做同样的事情吗?这是一个可重现的例子:

data(World, rivers, metro)

# creating two separate maps
africa <- World[World@data$continent=='Africa',]
asia <- World[World@data$continent=='Asia',]

my.breaks <- seq(0,80,20)

africa.map <- tm_shape(africa) + 
  tm_fill("HPI",style = 'fixed',breaks = my.breaks) + 
  tm_layout(bg.color = "white", legend.text.size = 1.3, legend.width = 0.6,
            legend.outside=TRUE, legend.outside.position = 'top', 
            legend.outside.size = .1, legend.position = c(0.8, 0.2))

asia.map <- tm_shape(asia) + 
  tm_fill("HPI",style = 'fixed',breaks = my.breaks) + 
  tm_layout(bg.color = "white", legend.text.size = 1.3, legend.width = 0.6,
            legend.outside=TRUE, legend.outside.position = 'top', 
            legend.outside.size = .1, legend.position = c(0.8, 0.2))

page.layout <- grid.layout(nrow = 8, ncol = 5,
                           widths = unit(c(1), "null"),
                           heights = unit(c(1), "null"),
                           default.units = "null",
                           respect = FALSE,
                           just = "centre")

grid.newpage()
pushViewport(viewport(layout = page.layout))
grid.text(paste('Happy Planet Index'), 
          vp = viewport(layout.pos.row = 1, layout.pos.col = 1:5),gp=gpar(fontsize=20))

grid.text('Africa', vp = viewport(layout.pos.row = 2, layout.pos.col = 1:2),gp=gpar(fontsize=20))
print(africa.map, vp=viewport(layout.pos.row = 3:6, layout.pos.col = 1:2))

grid.text('Asia', vp = viewport(layout.pos.row = 2, layout.pos.col = 3:5),gp=gpar(fontsize=20))
print(asia.map, vp=viewport(layout.pos.row = 3:6, layout.pos.col = 3:5))

最好的, 埃里希

不知道你是不是这个意思:

data(World)

tm_shape(World) +
    tm_polygons(c("economy", "HPI")) +
    tm_layout(legend.outside = TRUE)

常见的图例绘制在地图之外。由于两张图的图例不同,所以只取第一张图的图例

还有一些方法可以使用grid.layout。在这种情况下,您需要在网格视口中打印 tmap 地图(参见 print.tmap),并在另一个视口中打印图例。

更新:

为了完整起见:通常,应该有一种方法可以用分面来做到这一点:

data(World)
AfAs <- World[World@data$continent %in% c('Africa', 'Asia'),]
tm_shape(AfAs) + 
    tm_fill("HPI",style = 'fixed',breaks = my.breaks) + 
    tm_facets(by = "continent", drop.units = TRUE, free.coords = TRUE)

如果需要绘制两个 tmap 调用,将图例作为单独的地图处理是最方便的,legend.only=TRUE:

africa.map <- tm_shape(africa) + 
    tm_fill("HPI",style = 'fixed',breaks = my.breaks) +
    tm_layout(legend.show = FALSE)

asia.map <- tm_shape(asia) + 
    tm_fill("HPI",style = 'fixed',breaks = my.breaks) +
    tm_layout(legend.show = FALSE)

legend.map <- tm_shape(africa) + 
    tm_fill("HPI",style = 'fixed',breaks = my.breaks) +
    tm_layout(legend.only = TRUE)

grid.newpage()
page.layout <- grid.layout(nrow = 2, ncol = 2, widths=c(.4,.6), heights=c(.6,.4))
pushViewport(viewport(layout = page.layout))

print(africa.map, vp=viewport(layout.pos.row = 1:2, layout.pos.col = 1))
print(asia.map, vp=viewport(layout.pos.row = 1, layout.pos.col = 2))
print(legend.map, vp=viewport(layout.pos.row = 2, layout.pos.col = 2))

更新 2

图例可以用这段代码放大:

legend.map <- tm_shape(africa) + 
    tm_fill("HPI",style = 'fixed',breaks = my.breaks) +
    tm_layout(legend.only = TRUE, design.mode=TRUE, scale=2, asp=0)

design.mode=TRUE 在设计地图时非常方便。我不得不将 asp 设置为 0,因为它采用了非洲的 aspect 比率:这是一个错误,因为 aspect 比率应该遵循 device/viewport 当 legend.only=正确。这在开发版本中已修复。