在前面的推文里,小编介绍了R语言的基础绘图系统和tmap
工具包绘制地图的方法。ggplot2
工具包作为现在最受欢迎的绘图包,其本身绘制地图的功能并不算强大。但是ggplot2
有许多优秀的拓展包,它们共同构建了ggplot2
绘图系统,ggspatial
就是地图绘制方面的一个很常用的拓展包。
ggspatial
工具包的函数并不多,其主要作用就是弥补ggplot2
绘制地图方面的不足。比如,ggplot2
包的作者没有开发给地图添加指北针和比例尺的函数,而在专业的地图绘制中,这二者又必不可少。
library(ggplot2)
library(ggspatial)
library(patchwork)
在示例数据选取方面,小编尽量使用系统中自带的数据,而R语言系统中涉及中国的地理数据一般都属于“问题地图”,因此在这里使用美国的地理数据作为示例数据。
示例数据加载方式如下:
library(tidyverse)
data <- socviz::county_data
albersusa::counties_sf(proj = "laea") %>%
mutate(fips = as.character(fips)) %>%
left_join(data, by = c("fips" = "id")) -> usa
注:
socviz
和albersusa
两个工具包都需要通过github安装,不会安装的读者可以直接在后台输入关键词“示例数据”获取示例数据。
本篇推文一共介绍5个函数:
annotation_north_arrow:添加指北针
annotation_scale:添加比例尺
annotation_map_tile:添加背景地图
annotation_spatial_hline:添加水平线(纬线)
annotation_spatial_vline:添加垂直线(经线)
从函数名就可以看出,这些函数均属于ggplot2
绘图系统的注释类函数。
添加指北针的函数语法结构如下:
annotation_north_arrow(
mapping = NULL,
data = NULL,
...,
height = unit(1.5, "cm"),
width = unit(1.5, "cm"),
pad_x = unit(0.25, "cm"),
pad_y = unit(0.25, "cm"),
rotation = NULL,
style = north_arrow_orienteering
)
hegiht、width:控制指北针尺寸的参数;
pad_x、pad_y:控制指北针绝对位置的参数;
style:指北针的样式;
除上述参数外,该函数还有两个aesthetic类参数:which_north、location,分别控制指北针箭头的方向和指北针的相对位置,具体见下文示例。
默认状态的效果:
p <- ggplot(usa) +
geom_sf(color = NA, fill = "lightblue")
p + annotation_north_arrow()
位置调整:
pad_x
和pad_y
调整绝对位置;
location
调整相对位置:t(top)、b(bottom)、l(left)、r(right)。
p + annotation_north_arrow(
pad_x = unit(10, "cm"))
p + annotation_north_arrow(location = "br")
p + annotation_north_arrow(location = "br",
pad_x = unit(1, "cm"))
绝对位置参数的效果会受到地图输出尺寸的影响;
绝对位置和相对位置参数可以同时使用,即可以在相对位置的基础上使用绝对位置进行微调(图3)。
指北针方向:
which_north
参数默认设置为"grid"
,表示指北针始终垂直向上;
which_north
参数若设置为"true"
,表示指北针方向与其所在位置的纬线保持一致。
p + annotation_north_arrow(which_north = "true")
指北针的类型:
north_arrow_orienteering
north_arrow_fancy_orienteering
north_arrow_minimal
north_arrow_nautical
上述每种类型都对应一个函数,可以调用其参数对形态进行调整,以其中一个为例:
north_arrow_fancy_orienteering(
line_width = 1,
line_col = "black",
fill = c("white", "black"),
text_col = "black",
text_family = "",
text_face = NULL,
text_size = 10,
text_angle = 0
)
p + annotation_north_arrow(
style = north_arrow_fancy_orienteering(text_family = "mono",
text_face = "bold"))
添加比例尺的函数语法结构如下:
annotation_scale(
mapping = NULL,
data = NULL,
...,
plot_unit = NULL,
bar_cols = c("black", "white"),
line_width = 1,
height = unit(0.25, "cm"),
pad_x = unit(0.25, "cm"),
pad_y = unit(0.25, "cm"),
text_pad = unit(0.15, "cm"),
text_cex = 0.7,
text_face = NULL,
text_family = "",
tick_height = 0.6
)
bar_cols:比例尺中交替出现的颜色;
text_*:控制比例尺注释文本的参数;
aesthetic类参数:
width_hint:比例尺长度占地图宽度的比例;
unit_category:比例尺单位类型;"metric"表示公制单位(默认),"imperial"表示英制单位;
style:比例尺的类型,可选项有"bar"(默认)、"ticks";
location:比例尺相对位置;
line_col、text_col:线条、文本颜色。
默认效果:
p + annotation_scale()
调整部分参数后的效果:
p + annotation_scale(width_hint = 0.4,
unit_category = "imperial",
style = "ticks",
line_col = "red",
pad_y = unit(0.5, "cm"))
添加背景地图的函数语法结构如下:
annotation_map_tile(
type = "osm",
zoom = NULL, zoomin = -2,
forcedownload = FALSE,
cachedir = NULL,
progress = c("text", "none"),
quiet = TRUE, interpolate = TRUE,
data = NULL,
mapping = NULL, alpha = 1
)
type:背景地图类型;通过rosm
包的osm.types()
函数可查看所有可用类型;默认为;
zoom:背景地图的精细程度;数值越大精细度越高。
查看所有可用背景地图类型:
rosm::osm.types()
## [1] "osm" "opencycle" "hotstyle"
## [4] "loviniahike" "loviniacycle" "hikebike"
## [7] "hillshade" "osmgrayscale" "stamenbw"
## [10] "stamenwatercolor" "osmtransport" "thunderforestlandscape"
## [13] "thunderforestoutdoors" "cartodark" "cartolight"
ggplot(usa) +
geom_sf() +
annotation_map_tile(zoom = 5)
添加水平线的函数是annotation_spatial_hline()
,添加垂直线的函数是annotation_spatial_vline()
。这两个函数的语法结构是一样的,以前者为例:
annotation_spatial_hline(
mapping = NULL,
data = NULL,
stat = "identity",
...,
intercept = waiver(),
limits = NULL,
detail = 100,
crs = NULL,
na.rm = FALSE,
show.legend = NA
)
intercept:水平(垂直)位置;
limits:垂直(水平)范围;
crs:地理或投影坐标系。
其实更准确地说,这两个函数添加的分别是纬线和经线,因为当地理尺度较大且未投影时,它们绘制出并非是直线。
ggplot(usa) +
geom_sf(color = NA, fill = "lightblue") +
annotation_scale() +
annotation_spatial_hline(intercept = 33,
col = "red",
limits = c(-120, -60))
本例中的
crs
参数默认值为4326,即未进行投影;
intercept = 33
表示绘制北纬33度线;
limits = c(-120, -60)
表示在绘制纬线时,经度的范围是西经120度到西经60度。