使用 facet_wrap 绘制地图时在 ggplot 中动态拉伸形状

Dynamically stretching shapes in ggplot when graphing the map with use of the facet_wrap

我有兴趣改变 ggplot2 在使用 facet_wrap 绘图时处理 shapefile 的方式。我正在使用下面的代码为各种形状的组生成一个相当简单的地图:

# Data sourcing -----------------------------------------------------------

# Download an read US state shapefiles
tmp_shps <- tempfile(); tmp_dir <- tempdir()
download.file("http://www2.census.gov/geo/tiger/GENZ2014/shp/cb_2014_us_state_20m.zip",
              tmp_shps)
unzip(tmp_shps, exdir = tmp_dir)

# Libs
require(rgdal); require(ggplot2)

# Read
us_shps <- readOGR(dsn = tmp_dir, layer = "cb_2014_us_state_20m")
# Prepare data set for ggplot2
us_shps_frt <- fortify(us_shps, region = "NAME")
# Drop some to make smaller graphs for the example
us_shps_frt <- us_shps_frt[us_shps_frt$id == unique(us_shps_frt$id)[10:20],]


# Graph -------------------------------------------------------------------

ggplot(us_shps_frt, aes(long, lat, group = group, fill = id))  + 
    geom_polygon(colour = 'black', size = 0.5) + 
    coord_equal() +
    guides(fill = FALSE) +
    theme_bw() +
    facet_wrap(~id, ncol = 2) +
    ggtitle("Some Title") +
    theme(axis.text = element_blank(),
          axis.title = element_blank(),
          axis.ticks = element_blank(),
          panel.grid.minor = element_blank(),
          panel.grid.major = element_blank(),
          panel.border = element_blank())

如下图所示,在每个面内使用 space 并不理想,这使得形状难以阅读:

我有兴趣实现以下目标:

  1. 将分配给每个形状的白色 space 数量降至最低(只留下很小的边距)
  2. 在一个小平面内居中每个形状

我尝试了 coord_equal() 和自由秤的组合,如下面的代码片段所示:

# Desperate attempt
ggplot(us_shps_frt, aes(long, lat, group = group, fill = id))  + 
    geom_polygon(colour = 'black', size = 0.5) + 
    coord_equal() +
    guides(fill = FALSE) +
    theme_bw() +
    facet_wrap(~id, ncol = 2, scales = 'free') +
    coord_equal() +
    ggtitle("Some Title") +
    theme(axis.text = element_blank(),
          axis.title = element_blank(),
          axis.ticks = element_blank(),
          panel.grid.minor = element_blank(),
          panel.grid.major = element_blank(),
          panel.border = element_blank())

但结果毫无意义:

备注

使用 multiplot 函数并在循环中绘制单个图形的解决方案只有在以确保 R Markdown 文档中最终图形的方便可用性的方式提出时才会被接受。

首先:对于一个半复杂问题的完美可重现的例子,严重的荣誉。

这不是更多的工作:

# need this to ensure ggplot treats it as factor and so we can tell it
# not to drop the factor levels for the fill aesthetic
us_shps_frt$id <- factor(us_shps_frt$id)

# now we build a plot list
lapply(unique(us_shps_frt$id), function(x) {

  ggplot(dplyr::filter(us_shps_frt, id==x), 
         aes(long, lat, group = group, fill = id))  + 
    geom_polygon(colour = 'black', size = 0.5) + 
    coord_quickmap() +                   # better than the other coords_ for this
    guides(fill = FALSE) +
    theme_bw() +
    ggtitle(x) +                         # faux facet labels
    scale_fill_discrete(drop=FALSE) +
    theme(axis.text = element_blank(),
          axis.title = element_blank(),
          axis.ticks = element_blank(),
          panel.grid.minor = element_blank(),
          panel.grid.major = element_blank(),
          panel.border = element_blank())

}) -> states_list

# now mimic facet_wrap layout with grid.arrange
do.call(gridExtra::grid.arrange, c(states_list, ncol=2))