不废话,要做的事如标题。
假设我们有一个区域,在ArcGIS中长这个样子:

而假设我们已经有了他里面及周边的多种类型道路(例如高速、国道、市区道路等):

ps: OpenStreetMap上就能获得道路矢量图(shp),请自行取用
我们可以用R来批量计算这些道路长度。
首先读这个区域的多边形文件,并列出道路的shp文件名称:
rm(list = ls())
gc()
pacman::p_load(data.table, magrittr, dplyr, tidyr, sf, stringr)
region<-read_sf('map/oldcity.shp')
rdmaps<-c('H:/高速.shp',
'H:/高速引路.shp',
'H:/国道.shp',
'H:/省道.shp',
'H:/县道.shp',
'H:/市区一级道路.shp',
'H:/其它道路.shp',
'H:/行人道路.shp',
'H:/九级路.shp')
先读一个县道的文件,然后先与区域多边形文件intersection一下:
x<-rdmaps[5]
rddata<-read_sf(x, options = 'ENCODING=CP936') %>% st_intersection(region)
路名是中文,注意read_sf没有单独的encoding参数。读取之后直接与region叠加,叠加之后我们plot一下:
> plot(rddata)

这样看没感觉,在ArcGIS中对比一下:

看起来没问题。接着我们计算距离,计算几何距离的函数需要安装lwgeom包,如果没有的话会报错并提示:
> st_length(rddata)
Error in st_length(rddata) :
package lwgeom required, please install it first
用install.packages安装lwgeom,安装完之后再运行结果就出来了,默认单位为米:
> st_length(rddata)
Units: [m]
[1] 134.6967289 143.4617490 785.5871916 0.4189030 829.6537113 0.4306805 617.8162120
[8] 608.1285446
到这里,单文件的测试就完成了,我们写一个lapply循环然后合并结果:
result<-lapply(rdmaps, function(x) {
rddata<-read_sf(x, options = 'ENCODING=CP936') %>% st_intersection(region)
rddata<-data.table(rdname = sub(x, pattern = 'H:/', replacement = '') %>%
sub(pattern = '.shp', replacement = ''),
length = sum(st_length(rddata), na.rm = T))
return(rddata)
}) %>% rbindlist()
补充一点,sub用于字符串的替换,而.在函数里是转义符,要用两个反斜杠来消除转义规则。
合并之后print结果(result):
> result
rdname length
1: 高速 3120.194 [m]
2: 高速引路 0.000 [m]
3: 国道 13456.898 [m]
4: 省道 31839.923 [m]
5: 县道 10408.385 [m]
(下略)
到此结束。sf几乎支持所有基本的几何计算,要了解更多请阅读sf包的介绍页