如何使用 R 语言绘制双变量填充中国地图?

如何使用 R 语言绘制双变量填充中国地图?

在过去的教程中,我一直给大家分享的都是单变量填充地图的绘制方法,但是有时候我们想在一张地图上展示两个变量,这个时候该怎么绘制地图呢?我们可以选择双变量填充地图。如果我们在 Observable 上搜索“Bivariate Choropleth” 就可以看到一大堆使用 D3 绘制的双变量填充地图,非常炫酷,例如:https://observablehq.com/@d3/bivariate-choropleth

视频讲解

如何使用 R 绘制这种双变量填充地图,Timo Grossenbacher 做了一个非常炫酷的示范:

该图的绘制方法可以参考:https://timogrossenbacher.ch/2019/04/bivariate-maps-with-ggplot2-and-sf/ 学习。不过代码过于复杂,所以我这里对里面的代码进行了简化,并且介绍了如何绘制更多分阶的双变量填充地图(该作者只给出了三阶的画法)。

我暂时也没有时候绘制这种地图的数据,所以下面的演示中我是用随机生成的变量。

准备工作:

数据:

  1. county_simple.rds:中国县级地图(R 文件,sf 对象);
  2. china_full_map.json:中国省级地图数据(GEOJSON 格式);

加载 R 包:

1
2
3
4
5
6
7
8
9
10
library(sf)
library(ggspatial)
library(readr)
library(stringr)
library(tidyr)
library(purrr)
library(hrbrthemes)

# 设置字体
cnfont <- "SourceHanSerifSC-Medium"

我这里使用的是思源宋体,我这种字体设置的方法仅限 Mac 系统,Windows 系统请使用知识星球上介绍的方法设置。

准备数据

我随机生成了两个变量作为绘制双变量填充地图的“双变量”:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# 读入县级地图数据
read_rds('county_simple.rds') -> county_simple
# plot(county_simple[1])

# 生成示例数据
set.seed(1234)
county_simple %>%
st_drop_geometry() %>%
select(code = 县代码, name = 县) %>%
mutate(v1 = runif(2902, 1, 100),
v2 = runif(2902, 1, 100)) -> df
df

#> # A tibble: 2,902 x 4
#> code name v1 v2
#> <dbl> <chr> <dbl> <dbl>
#> 1 110101 东城区 12.3 34.3
#> 2 110102 西城区 62.6 4.61
#> 3 110105 朝阳区 61.3 38.6
#> 4 110106 丰台区 62.7 63.3
#> 5 110107 石景山区 86.2 48.2
#> 6 110108 海淀区 64.4 72.7
#> 7 110109 门头沟区 1.94 3.24
#> 8 110111 房山区 24.0 50.9
#> 9 110112 通州区 66.9 56.6
#> 10 110113 顺义区 51.9 88.9
#> # … with 2,892 more rows

数据非常简单,就是每个区县对于两个变量的两个值,v1 和 v2 就是我们需要的 “bivariate”。

上面我展示的图片中使用的是三阶,我自然得比他的更复杂点,我用 4 阶!下面我们将变量 v1 和 v2 使用分位数各分成 4 段:

代码去哪了?

代码可以加入我的知识星球后从知识星球下载附件获取~
要了解如何加入我的知识星球,可以阅读关于界面或者添加我的微信咨询。

对 df 里的 v1 v2 进行分组:

代码去哪了?

代码可以加入我的知识星球后从知识星球下载附件获取~
要了解如何加入我的知识星球,可以阅读关于界面或者添加我的微信咨询。

这样我们就把数据都分好组了,下面最重要的事情来了?两个变量,那每组应该是什么颜色?不用担心,前人已经把工具开发好了:Bivariate Choropleth Color Generator(超链接已隐藏)

这个工具可以让你自由的进行颜色选择、色阶选择,完美!这里我们选择 4 阶的:对应的颜色是:

代码去哪了?

代码可以加入我的知识星球后从知识星球下载附件获取~
要了解如何加入我的知识星球,可以阅读关于界面或者添加我的微信咨询。

可以用 R 查看这些颜色:

代码去哪了?

代码可以加入我的知识星球后从知识星球下载附件获取~
要了解如何加入我的知识星球,可以阅读关于界面或者添加我的微信咨询。

我们使用这些颜色构建一个数据框,这个数据框是用于接下来绘制图例的:

代码去哪了?

代码可以加入我的知识星球后从知识星球下载附件获取~
要了解如何加入我的知识星球,可以阅读关于界面或者添加我的微信咨询。

我们把这个数据框和 df 合并起来:

代码去哪了?

代码可以加入我的知识星球后从知识星球下载附件获取~
要了解如何加入我的知识星球,可以阅读关于界面或者添加我的微信咨询。

再把 df 和地图数据集合并起来:

代码去哪了?

代码可以加入我的知识星球后从知识星球下载附件获取~
要了解如何加入我的知识星球,可以阅读关于界面或者添加我的微信咨询。

再读入省级地图数据,这个是覆盖在县级地图上面让地图更好看的:

1
2
# 省级地图数据
prov <- read_sf('china_full_map.json')

生成一个标签数据框,这个数据框是用于给地图添加注解的,因为我想像上面的瑞典地图一样在地图的四角选择四个县通过箭头添加注解文本:

代码去哪了?

代码可以加入我的知识星球后从知识星球下载附件获取~
要了解如何加入我的知识星球,可以阅读关于界面或者添加我的微信咨询。

这里为了满足“四角”的要求,我从新疆、云南、江苏和辽宁四个省选取了四个极端组的县进行标注。labeldf 数据框中的 x 和 y 就是选取的四个极端县的质心,同时也是绘图时箭头的箭尾坐标,xend、yend 是箭头坐标,是我试出来的。xla 和 yla 是标签放置的坐标,也是我试出来的。label 则是用于标注的文本,\n 表示换行。

然后我们就可以绘制地图了:

代码去哪了?

代码可以加入我的知识星球后从知识星球下载附件获取~
要了解如何加入我的知识星球,可以阅读关于界面或者添加我的微信咨询。

这里我之所以还把经纬网保留,是因为有人不相信那个方向是北。。。在兰勃特等角投影下,这个方向就是北的。

绘制图例需要这样的数据:

代码去哪了?

代码可以加入我的知识星球后从知识星球下载附件获取~
要了解如何加入我的知识星球,可以阅读关于界面或者添加我的微信咨询。

绘制图例:

代码去哪了?

代码可以加入我的知识星球后从知识星球下载附件获取~
要了解如何加入我的知识星球,可以阅读关于界面或者添加我的微信咨询。

最后就是把这两个图组合在一起了:

代码去哪了?

代码可以加入我的知识星球后从知识星球下载附件获取~
要了解如何加入我的知识星球,可以阅读关于界面或者添加我的微信咨询。

知识星球附件链接:https://t.zsxq.com/QbE6Qrv

#

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×