转摘技巧 | 如何使用R语言的常用工具包绘制双变量填充地图

允若彤阅读量 10

之前本号转载了DataCharm公众号的一篇推送:

  • [转载 | 双变量映射地图可视化绘制方法](https://mp.weixin.qq.com/s?__biz=Mzg2MjU1NjQ4NQ==&idx=1&mid=2247484033&scene=21&sn=7ffaaae29489601e61877c4463f45dad#wechat_redirect)

这篇推送使用了biscale工具包绘制了双变量填充地图。近来,小编发现使用常用的绘图工具包也能很便捷的绘制这种地图,而且灵活性更强一些。

1 示例数据

本篇使用的示例数据和上面转载的推送一样,关于数据的介绍可以点击上面的推送链接查看。

go 复制代码
library(tidyverse)
data <- socviz::county_data

albersusa::counties_sf(proj = "laea") %>%
  mutate(fips = as.character(fips)) %>%
  left_join(data, by = c("fips" = "id")) -> usa
  • 示例数据来自socvizalbersusa两个工具包,目前它们都只能通过github安装。不会安装的读者可以在公众号后台发送关键词"示例数据"获取。

2 准备工作

灵感来自Nature上的一篇论文:

这篇论文绘制的双变量填充地图是这样的:
![](https://img-blog.csdnimg.cn/img_convert/d1ce263e3e9c61ad007bb669c2511302.png)

要想绘制这样的地图,关键是要定义两个方向的渐变颜色,这里直接使用了上述论文所定义的颜色,然后使用sf工具包的网格生成函数制作了图例,后续只要把这个图例与主图拼接在一起就行了。

go 复制代码
library(sf)
# 选择颜色
colors <- list(c(249, 244, 248), c(205, 216, 236), 
               c(177, 203, 230), c(138, 181, 223),
               c(239, 212, 219), c(202, 190, 210), 
               c(175, 176, 207), c(131, 160, 204),
               c(237, 170, 179), c(197, 163, 187), 
               c(157, 145, 183), c(130, 142, 190),
               c(234, 129, 143), c(192, 130, 155),
               c(161, 129, 166), c(121, 122, 170))
colors <- sapply(colors, function(x) 
  do.call('rgb', c(as.list(x), maxColorValue = 255)))
comb <- outer(1:4, 1:4, paste0) %>% c()
coldf <- data.frame(col = colors, comb = comb) %>%
  mutate(col = as.character(col))
# 生成网格
pts <- rbind(c(0,0), c(0, 4),c(4,4), c(4,0), c(0,0))
sfc <- st_sfc(st_polygon(list(pts)))
grid <- st_make_grid(sfc, n = c(4,4))
Legend <- st_sf(geom = grid, label = coldf$col)
Legend$col <- coldf$col
# 可视化
plot(st_geometry(Legend), col = Legend$col, border = NA)

![](https://img-blog.csdnimg.cn/img_convert/1775731e8ac38775e7ade0e56e2def6b.png)

通过给矢量对象及其属性变量一个固定的命名,在更换绘图数据或变量时只需在下面代码中相应位置修改即可:

go 复制代码
Shp <- usa %>%
  mutate(Var01 = hh_income) %>%
  mutate(Var02 = travel_time)
  • 这里和转载推文一样,使用hh_incometravel_time作为绘图映射变量。

生成示例对象的边界、将属性变量由连续变量转换为分类变量:

go 复制代码
Border <- st_union(Shp)
Shp %>%
  mutate(A = as.numeric(cut(Var01, include.lowest = T,
                            breaks = quantile(Var01, na.rm = T,
                                              probs = c(0, 0.25,
                                                        0.5, 0.75, 1)))),
         B = as.numeric(cut(Var02, include.lowest = T,
                            breaks = quantile(Var02, na.rm = T,
                                              probs = c(0, 0.25,
                                                        0.5, 0.75, 1)))),
         comb = paste0(A, B)) %>%
  left_join(coldf, by = "comb") -> Shp
  • 这里使用的是四分位分类法,如果有需要在probs参数中可以修改相应的分位数,或者选用其他分类方法。

3 常用工具包

R语言中常用的绘图系统主要是基础绘图系统graphicsggplot2两种,另外,tmap是专门绘制地图的工具包。本文分别使用这三个常用工具包来绘制双变量填充地图。

3.1 graphics

绘制方法如下:

go 复制代码
# 主图
par(fig = c(0,0.9,0,1), plt = c(0,1,0.05,1), family = "mono")
plot(st_geometry(Shp), col = Shp$col, border = NA)
plot(Border, cex = 1, lwd = 2, add = T)
# 图例
par(fig = c(0.85,1,0.1,0.35), plt = c(0,1,0.1,1))
par(new = T, mgp = c(0,0,-2))
plot(st_geometry(Legend), col = Legend$col, border = NA)
mtext("hh_income", side = 1)
mtext("travel_time", side = 2)

![](https://img-blog.csdnimg.cn/img_convert/f99371c5ac5c1f3a8d3060b64fddccba.png)

  • 使用graphics工具包中的函数绘制地图需要加载sf工具包;

  • 通过par函数的fig参数控制主图和图例的位置,该参数的元素使用的是相对尺度,即把内边框的长、宽作为1个单位长度,具体可见推文[graphics | 基础绘图系统(二)------ 绘图参数及par函数](https://mp.weixin.qq.com/s?__biz=Mzg2MjU1NjQ4NQ==&idx=1&mid=2247484941&scene=21&sn=b18bfa0e0602f8c9091d306057c6c3fc#wechat_redirect)中的布局参数

  • mtext函数中需要修改相应的变量或标签名称。

3.2 ggplot2

绘制方法如下:

go 复制代码
library(ggplot2)
# 主图
ggplot(Shp) +
  geom_sf(aes(fill = I(col)), col = NA) +
  theme_void() +
  theme(text = element_text(family = "mono"))-> main
# 图例
ggplot(Legend) +
  geom_sf(aes(fill = I(col)), col = NA) +
  labs(x = "hh_income", y = "travel_time") +
  theme_void() +
  theme(text = element_text(family = "mono"),
        axis.title = element_text(),
        axis.title.y = element_text(angle = 90)) -> legend
# 组合
library(cowplot)
ggdraw() +
  draw_plot(main, 0, 0, 0.9,1) +
  draw_plot(legend, 0.75, 0.05, 0.25, 0.25)

![](https://img-blog.csdnimg.cn/img_convert/0a03ec667d2d95222cdf06df27cd1298.png)

  • 拼接ggplot2工具包绘制的图形需要借助cowplot工具包,因此需要对主图和图例分别进行命名;

  • draw_plot函数同样使用的是相对尺度的坐标方式。

3.3 tmap

绘制方式如下:

go 复制代码
library(tmap)
# 主图
tm_shape(Shp) +
  tm_fill(col = "col") +
  tm_shape(Border) +
  tm_borders(lwd = 2) +
  tm_compass(position = c(0.75, 0.85), size = 2.5) +
  tm_scale_bar(position = c(0.6, 0.01), text.size = 0.8) +
  tm_legend(show = F) +
  tm_layout(frame = F, fontfamily = "mono") -> main
main
# 图例
tm_shape(Legend) +
  tm_fill("col") +
  tm_xlab("hh_income") +
  tm_ylab("travel_time") +
  tm_layout(frame = F, fontfamily = "mono") -> legend
legend

![](https://img-blog.csdnimg.cn/img_convert/bc48959d63818d19aac5d2b565c70a80.png) 主图 ![](https://img-blog.csdnimg.cn/img_convert/20eb3720a0130fe776aedd31a9acdc49.png) 图例

  • tmap作为专门的地图绘制工具包,其语法结构类似于ggplot2,因此对于习惯使用ggplot2绘图的读者很容易入门和掌握。

目前小编还没发现完美拼接tmap绘制的地图的方法,tmap_arrage函数达不到相应的效果:

go 复制代码
tmap_arrange(main, legend, ncol = 2,
             widths = c(0.75, 0.25))

![](https://img-blog.csdnimg.cn/img_convert/7ce7719333fed6d52c21221d5298ceb4.png)

  • 该函数只能将主图和图例拼接成并列的两列,而不能将图例缩小放到右下角;替代方法是分别导出主图和图例,然后使用Adobe Illustrator软件进行手动调整。

4 比较

4.1 优劣比较

这三个工具包各有优劣:

  • graphics使用自有参数就可以实现灵活的图形拼接功能,运行速度也较快,但是绘制地图时无法添加指北针和比例尺等地图要素;

  • ggplot2是比较流行的绘图工具包,其绘制地图的功能可能有限,但它有诸多拓展包,从而可以实现灵活拼接、添加指北针和比例尺等功能,不过这也增加了其学习难度;

  • tmap作为专业的地图绘制工具包,可以很方便地添加各种地图要素,缺点是它的图形拼接功能比较有限,而且加载该工具包极为耗时。

4.2 颜色参数比较

这三个工具包中的绘图函数都拥有多个与颜色相关的参数,辨析如下:

  • graphics中的plot函数,col参数不能用于映射,其取值只能是颜色编码,并按照行序依次循环赋予给相应的空间单元;palette参数用于映射,并结合breaksnbreaks参数使用;border参数用于给空间单元的边界上色。这里使用的是col参数并设置border = NA,以消除内部边界;

  • ggplot2中的geom_sf函数,fillcol参数均有映射和非映射两种用法,其中前者用于空间单元的填充色,后者用于给边界上色。这里使用fill的映射用法并设置col = NA,以消除内部边界;

  • tmap中的tm_fill函数,该函数只针对填充色进行设置,col参数有映射和非映射两种用法,无论是否映射,其取值都需要加引号""palette参数为非映射用法,用于为col参数的映射提供对应的颜色编码;若col参数映射的变量本身就是颜色编码时,则会忽略palette参数;设置边界需要调用tm_border函数。这里设置col = "col",其中col变量本身为颜色编码,不调用tm_border函数则默认不显示边界。


往期推荐阅读:

  • [《数据处理通识》专辑-base | 使用apply族函数进行向量化运算](https://mp.weixin.qq.com/s?__biz=Mzg2MjU1NjQ4NQ==&idx=1&mid=2247484528&scene=21&sn=599c4bc30cdb4bb4b7e38d7b4df4fe5e#wechat_redirect)

  • [《制表与可视化》专辑-ggplot2 | ggplot2作图语法入门](https://mp.weixin.qq.com/s?__biz=Mzg2MjU1NjQ4NQ==&idx=1&mid=2247486538&scene=21&sn=4692d9129a2e3b46f84fc77444d67096#wechat_redirect)

  • [《数学模型》专辑-car | 线性回归(三)------残差分析和异常点检验](https://mp.weixin.qq.com/s?__biz=Mzg2MjU1NjQ4NQ==&idx=1&mid=2247486695&scene=21&sn=c055ffd59a67911ed71b740b8424fd59#wechat_redirect)

  • [《地理计算与分析》专辑-spdep | 如何在R语言中计算空间自相关指数](https://mp.weixin.qq.com/s?__biz=Mzg2MjU1NjQ4NQ==&idx=1&mid=2247486134&scene=21&sn=4c2905d6bb37084a9606cf4e7d57f78b#wechat_redirect)

![](https://img-blog.csdnimg.cn/img_convert/1a197ddfcaf766c954caa410b3b80126.png)

复制代码
    ```
    

    ===========================
    【来源: CSDN】
    【作者: R语言学堂】
    【原文链接】 https://blog.csdn.net/weixin_54000907/article/details/117138180
    声明:转载此文是出于传递更多信息之目的。若有来源标注错误或侵犯了您的合法权益,请作者持权属证明与本网联系,我们将及时更正、删除,谢谢。
    ```
0/300
全部评论0
0/300