GIS 中的矢量数据和栅格数据(二)

GIS 中的矢量数据和栅格数据(二)

今天我们来看如何在 R 中绘制地图数据,能画地图数据的包很多,如果你熟悉 ggplot2 又不关心是否能交互,那就用 ggplot2;如果你侧重交互性,可以考虑 leaflet;如果仅仅是想在地图上探索地理对象,可以用 mapview;如果上面几种特性都不满足你的要求,try tmap! tmap 可以加载 sf, raster ,Spatial 类的数据。

安装包

1
2
3
4
5
install.packages("tmap")
# 或者
library(devtools)
install_github("mtennekes/tmaptools")
install_github("mtennekes/tmap")

我们通过一张图来看 tmap 的使用方法

下载数据

首先我们加载一个练习用的数据,如果加载不了,可以私信 TidyFriday 索取

1
load("sample.RData")

这个数据中包含5个图层数据:
|图层|代表的数据|
|—|—|
|elev.r|海拔栅格数据|
|inter.sf|洲际公路线|
|p.sf|城市点数据|
|rail.sf|铁路线|
|s.sf|缅因州的郡县边界线|

我们随便来查看一个数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
str(s.sf)
#> Classes ‘sf’ and 'data.frame': 16 obs. of 6 variables:
#> $ NAME : Factor w/ 16 levels "Androscoggin",..: 2 13 11 10 15 4 9 14 6 1 ...
#> $ Income : int 21024 21025 21292 23307 20015 21744 21885 23020 25652 24268 ...
#> $ NoSchool : num 0.01339 0.00521 0.00634 0.00685 0.00478 ...
#> $ NoSchoolSE: num 0.001407 0.00115 0.002129 0.001025 0.000966 ...
#> $ IncomeSE : num 251 391 724 242 327 ...
#> $ geometry :sfc_MULTIPOLYGON of length 16; first list element: List of 1
#> ..$ :List of 1
#> .. ..$ : num [1:32, 1:2] 513821 513806 445039 422284 424687 ...
#> ..- attr(*, "class")= chr "XY" "MULTIPOLYGON" "sfg"
#> - attr(*, "sf_column")= chr "geometry"
#> - attr(*, "agr")= Factor w/ 3 levels "constant","aggregate",..: NA NA NA NA NA
#> ..- attr(*, "names")= chr "NAME" "Income" "NoSchool" "NoSchoolSE" ...

我们可以看到 s.sf 中包含6个变量,16个观测值,我们可以像操作 dataframe 一样操作它

绘制 sf 数据

首先我们绘制个空白地图:

1
2
library(tmap) 
tm_shape(s.sf) + tm_polygons(col="green", border.col="black")

接着我们可以把其他变量例如收入 Income,映射到地图上

1
tm_shape(s.sf) + tm_polygons(col="Income", border.col="black")

语法也很好理解,tm_shape 用来加载数据,tm_polygons 用来定义几何对象,类似 geom_*;详细的参数解释可以通过 ?tm_shape 来查询。

图例放在一起看着有点拥挤,我们把它挪出来:

1
2
tm_shape(s.sf) + tm_polygons("Income",  border.col = "white") + 
tm_legend(outside = TRUE)

如果我们想要个简洁点的,不要图例也不要边框;

1
2
3
tm_shape(s.sf) + 
tm_polygons("Income", border.col = "white", legend.show=FALSE) +
tm_layout(frame = FALSE)

只是郡县的边界线不想要了,设置 border.col 就可以啦:

1
2
3
tm_shape(s.sf) + 
tm_polygons("Income", border.col = NULL) +
tm_legend(outside = TRUE)

和 ggplot 一样,我们想要什么图层直接网上➕就可以了:

1
2
3
4
5
tm_shape(s.sf) + 
tm_polygons("Income", border.col = NULL) +
tm_legend(outside = TRUE) +
tm_shape(rail.sf) + tm_lines(col="grey70") +
tm_shape(p.sf) + tm_dots(size=.3, col="black")

铁路线和城市点图就出来了

我们观察下前面收入的图例,是不是渐变不太好区分,我们可以人为对数据进行分箱,比如我们把 Income 分成6个等级画图:

1
2
3
tm_shape(s.sf) + 
tm_polygons("Income", style = "quantile", n = 6, palette = "Greens") +
tm_legend(outside = TRUE)

style 支持的参数还不少呢,如果我们想人为指定分割点,可以用参数 fixed ,要想分成三类,就传 4 个点:

1
2
3
4
tm_shape(s.sf) + 
tm_polygons("Income", style = "fixed",palette = "Greens",
breaks = c(0, 23000, 27000, 100000 )) +
tm_legend(outside = TRUE)

再给每个分类加上自己的 label,指定文字大小:

1
2
3
4
5
6
tm_shape(s.sf) + 
tm_polygons("Income", style = "fixed",palette = "Greens",
breaks = c(0, 23000, 27000, 100000 ),
labels = c("under $23,000", "$23,000 to $27,000", "above $27,000"),
text.size = 1) +
tm_legend(outside = TRUE)

palette 跟 ggplot 中的颜色设置是类似的,既可以传入名称也可以传入色带:

1
2
3
tm_shape(s.sf) + 
tm_polygons("NAME", palette = "Pastel1") +
tm_legend(outside = TRUE)

添加更丰富的 label 和 text,并调整布局:

1
2
3
4
5
6
tm_shape(s.sf) + 
tm_polygons("NAME", palette = "Pastel1", border.col = "white") +
tm_legend(outside = TRUE) +
tm_shape(p.sf) +
tm_dots(size= .3, col = "red") +
tm_text("Name", just = "left", xmod = 0.5, size = 0.8)

给地图数据添加网格线:

1
2
3
4
5
6
tm_shape(s.sf) + 
tm_polygons("NAME", palette = "Pastel1") +
tm_legend(outside = TRUE) +
tm_layout(outer.margins = c(.1,.1,.1,.1)) +
tm_grid(labels.inside.frame = FALSE,
n.x = 4, n.y = 5)

投影坐标系转换为 longlat 格式的:

1
2
3
4
5
6
7
8
tm_shape(s.sf) + 
tm_polygons("NAME", palette = "Pastel1") +
tm_legend(outside = TRUE) +
tm_layout(outer.margins = c(.1,.1,.1,.1)) +
tm_grid(labels.inside.frame = FALSE,
x = c(-70.5, -69, -67.5),
y = c(44, 45, 46, 47),
projection = "+proj=longlat")

再精细一点,加一个°的标识:

1
2
3
4
5
6
7
8
9
tm_shape(s.sf) + 
tm_polygons("NAME", palette = "Pastel1") +
tm_legend(outside = TRUE) +
tm_layout(outer.margins = c(.1,.1,.1,.1)) +
tm_grid(labels.inside.frame = FALSE,
x = c(-70.5, -69, -67.5) ,
y = c(44, 45, 46, 47),
projection = "+proj=longlat",
labels.format = list(fun=function(x) {paste0(x,intToUtf8(176))} ) )

176 就是°的 unicode 码,我们转成 utf-8 就可以显示了

我们再加一个条形统计图

1
2
3
4
tm_shape(s.sf) + 
tm_polygons("NoSchool", palette = "YlOrBr", n = 6,
legend.hist = TRUE, title = "% no school") +
tm_legend(outside = TRUE, hist.width = 2)

绘制 raster 数据

当然我们也可以绘制 raster 数据:

1
2
3
4
tm_shape(elev.r) + 
tm_raster(style = "cont", title = "Elevation (m)",
palette = terrain.colors(64))+
tm_legend(outside = TRUE)

同 sf 数据一样,也可以自己定义分箱点:

1
2
3
4
5
tm_shape(elev.r) + 
tm_raster(style = "fixed", title = "Elevation (m)",
breaks = c(0, 50, 100, 500, 750, 1000, 15000),
palette = terrain.colors(5))+
tm_legend(outside = TRUE)

自定义颜色并添加个统计图

1
2
3
4
5
tm_shape(elev.r) + 
tm_raster(style = "quantile", n = 12, title = "Elevation (m)",
palette = colorRampPalette( c("darkolivegreen4","yellow", "brown"))(12),
legend.hist = TRUE)+
tm_legend(outside = TRUE, hist.width = 2)

有几个图我想同时展示,没问题,tmap 自带了 tmap_arrange!

1
2
3
4
5
6
7
8
inc.map <- tm_shape(s.sf) + tm_polygons(col="Income")+
tm_legend(outside=TRUE)
school.map <- tm_shape(s.sf) + tm_polygons(col="NoSchool")+
tm_legend(outside=TRUE)
name.map <- tm_shape(s.sf) + tm_polygons(col="NAME")+
tm_legend(outside=TRUE)

tmap_arrange(inc.map, school.map, name.map)

facets? No Problem!

1
2
3
tm_shape(s.sf) + tm_polygons(col = "Income")+
tm_legend(outside = TRUE) +
tm_facets( by = "NAME", nrow = 2)

感受到 tmap 的强大气场了吗?假如你还想更精细的调节你的 tmap 图表,去他的官网查看吧!

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

# R

评论

Your browser is out-of-date!

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

×