ggplot2 案例:大城市发展的有多快?

ggplot2 案例:大城市发展的有多快?

在之前的推文「新冠肺炎的感染者们都在哪呢?」中我介绍了如何使用 ggplot2 绘制气泡地图,昨天布置了一个作业,今天我们来公布一份参考答案吧!

首先我们导入我们需要的 R 包:

1
2
3
4
5
library(sf)
library(readr)
library(tidyverse)
library(hrbrthemes)
library(ggtext)

ggtext 包可以从我的服务器上安装:

1
install.packages("https://czxa.top/pkg/ggtext_0.1.0.tar.gz", repos = NULL, type = "source")

我们再读取一份世界地图数据, world.geo.json,是一份带中国南海九段线的世界地图数据。这份数据在文末有下载方法。

1
2
3
# 世界地图数据
worldmap <- read_sf('world.geo.json') %>%
st_transform(crs = 4326)

sf 包的 read_sf 函数可以将 geojson 格式的数据读取为 sf 对象(也是数据框,很容易处理)。st_transform 函数用于对 sf 数据框进行坐标系变换,这里使用 4326 坐标系,这种坐标系的经线是相互平行的。

然后我们读取并处理数据(示例数据集的获取方式也在文末):

1
2
3
4
read_csv('data-bKvwd.csv') %>% 
st_as_sf(coords = c("Lon", "Lat"), crs = 4326) %>%
select(`2000-2016`, category, geometry) %>%
mutate(`2000-2016` = as.numeric(`2000-2016`)) -> df

st_as_sf 函数可以把经纬度变量转换成 sf 的 geometry 变量,同时该数据框也会被转为 sf 对象,这里我使用的也是 4326 坐标系,这样等下绘图的时候地图图层和数据图层才不会“分家”。

然后我们就可以绘图了!为了清晰的展示 ggplot2 各个语句的作用,我一步步来:

首先绘制地图图层和数据图层:

1
2
3
4
5
6
7
ggplot(worldmap) + 
geom_sf(size = 0.1, color = "black",
fill = "#F3F3F3") +
geom_sf(data = df, aes(size = `2000-2016` + 1,
color = category),
alpha = 0.5) -> p1
p1

修改绘图主题,这里我使用 hrbrthemes 包的 theme_ipsum 主题:

1
2
3
4
5
6
p1 + 
theme_ipsum(base_family = cnfont,
subtitle_family = cnfont,
caption_family = cnfont,
grid = "") -> p2
p2

worldtilegrid 包的 theme_enhance_wtg() 函数可以用于快速去除轴标签等:

1
2
3
p2 + 
worldtilegrid::theme_enhance_wtg() -> p3
p3

前面的数据图层里面我的 size 映射的是 2000-2016 + 1,之所以 + 1 是因为变量 2000-2016 里面有些观测值是负数,size 参数不能为负数。下面我们设定 size 的映射规则:

1
2
p3 + scale_size_continuous(range = c(1, 5)) -> p4
p4

同样我们再设定 color 的映射规则:

1
2
3
4
5
6
7
p4 + 
scale_color_manual(values = c("negative" = "#FDAB62",
"between 0 and 2.5" = "#9CDAE6",
"between 2.5 and 5" = "#189DB6",
"5 or more" = "#244C6A",
"null" = NA)) -> p5
p5

经纬度线和图例我们是不需要的,所以删除,删除图例的一个常用方法是设置 legend.position = "none",经纬度线对应的元素是 panel.grid.major 和 panel.grid.minor,设定它们为空元素(element_blank())即可:

1
2
3
4
5
p5 + 
theme(legend.position = "none",
panel.grid.major = element_blank(),
panel.grid.minor = element_blank()) -> p6
p6

最后我们添加各种文本标签,例如标题、副标题:

1
2
3
4
5
6
p6 + 
labs(title = "大城市发展的有多快?",
subtitle = "该图展示了 2016 年所有人口超过 100 万的大城市,圆圈的大小和颜色表示 2000 年到 2016 年间城市人口的平均增长速度。<b><span style='color:\"#FDAB62\"'>负增长</span>/<span style='color:\"#9CDAE6\";'>0 - 2.5%</span>/<span style='color:\"#189DB6\";'>2.5% - 5%</span>/<span style='color:\"#244C6A\";'>超过 5%</span></b>",
caption = "数据来源: How fast do big cities grow? | Created with Datawrapper\n<https://www.datawrapper.de/_/bKvwd/>\n绘制:TidyFriday") +
theme(plot.subtitle = element_textbox_simple()) -> p7
p7

这里我的副标题使用了 HTML 标签来定义颜色,这是 ggtext 包中定义的用法,为了使得这种设定生效,需要设定 plot.subtitle = element_textbox_simple()

最后我们更改地图的投影坐标系,我不是很喜欢经线相互平行的这种坐标系,因为这种坐标系过度放大了两级地区(例如俄罗斯),下面我使用了 eck4 坐标系:

1
2
3
p7 + 
coord_sf(crs = "+proj=eck4") -> p8
p8

这样我们就把这幅图画完了,之所以不需要图例,是因为我们的副标题的结尾具有图例的效果了。

结尾彩蛋:

下载 world.geo.json 文件:

1
download.file("https://czxa.top/pkg/world.geo.json", "world.geo.json")

下载 data-bKvwd.csv 文件:

1
download.file("https://czxa.top/pkg/data-bKvwd.csv", "data-bKvwd.csv")

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

#

评论

Your browser is out-of-date!

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

×