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

时间:2015-09-24 16:54:19

标签: r ggplot2 gis shape rgdal

我有兴趣在使用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())

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

Small shapes

我有兴趣实现以下目标:

  1. 将分配给每个形状的空白量最小化(仅留下很小的边距)
  2. 将小平面内的每个形状居中
  3. 我尝试了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())
    

    但结果毫无意义:

    more messy shapes

    注释

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

1 个答案:

答案 0 :(得分:2)

首先:对半复杂问题的完全可重复的例子表示严肃的赞誉。

这不是更多的工作:

# 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))

enter image description here