R语言储存矢量数据(.shp)目前有两种规范:
第一种规范来自sp
工具包,数据以Spatial*DataFrame形式储存,执行的标准来自Esri shapefile的相关方法,其定义的数据结构与R中基本的数据结构有着较大的区别。它更多的关注数据中的空间信息,数据结构比较复杂。这种数据格式要素类型又可细分为如下几类:
-
SpatialPointsDataFrame
-
SpatialLinesDataFrame
-
SpatialPolygonsDataFrame
-
....
第二种规范来自sf
工具包,它制定了一种新的储存空间数据的标准,是将空间数据中每个要素看做是一个simple feature,数据结构按照要素展开,每个要素信息单独占一行,其属性数据分别对应各列,而空间信息也作为一种属性占据一列。这样从外观上看,空间数据与R中普通的数据框(data.frame)并无太大区别,使得数据结构比较清晰。
图片地址:https://mirrors.tuna.tsinghua.edu.cn/CRAN/web/packages/sf/vignettes/sf1.html
1 读取矢量数据
R中有多个工具包可以读取矢量数据,常用的有maptools
中的readShapeSpatial()
系列函数,rgdal
中的readOGR()
和sf
中的st_read()
,前两个函数读取的文件以Spatial*DataFrame(sp)格式保存,最后一个函数读取的文件以sf格式保存。
准备示例文件:
library(tidyverse)
library(sf)
nc <- st_read(system.file("shape/nc.shp", package = "sf"))
nc2 <- mutate(nc, AREA = "面积")
# 自定义文件夹位置
st_write(nc, "G:/北卡罗来纳州.shp", delete_layer = T) # 文件名含中文
st_write(nc2, "G:/nc2.shp", delete_layer = T) # 文件内含中文
st_write(nc, "G:/nc.shp", delete_layer = T) # 不含中文
1.1 readShapeSpatial()
library(maptools)
sp11 <- readShapeSpatial("G:/北卡罗来纳州.shp") # 文件名含有中文字符,无法运行
sp12 <- readShapeSpatial("G:/nc2.shp") # 文件名无中文字符,文件内容含有中文字符,可以运行
sp13 <- readShapeSpatial("G:/nc.shp") # 文件名和文件内容均无中文字符,可以运行
readShapeSpatial()
是一个通用函数,根据要素类型,还可以使用readShapePoints()
,readShapeLines()
和readShapePoly()
等子函数。
这个函数相比于另外两个函数存在诸多缺点,已经被停止维护了,使用时会出现以下提示:
readShapeSpatial is deprecated; use rgdal::readOGR or sf::st_read
而对于中国用户来说,其最大的缺点可能就是不能读取以中文命名的文件了;若只是属性表中含有中文字符也可以读取。
1.2 readOGR()
library(rgdal)
sp21 <- readOGR(dsn = "G:/", layer = "北卡罗来纳州",
stringsAsFactors = F,
use_iconv = TRUE,
encoding = "UTF-8")
sp22 <- readOGR(dsn = "G:/", layer = "nc2",
stringsAsFactors = F,
use_iconv = TRUE,
encoding = "UTF-8")
sp23 <- readOGR(dsn = "G:/", layer = "nc",
stringsAsFactors = F)
class(sp23) # 查看数据类型
# 部分输出结果
> class(sp23) # 查看数据类型
[1] "SpatialPolygonsDataFrame"
attr(,"package")
[1] "sp"
readOGR()
函数相比于readShapeSpatial()
实用性更强,但也存在很多缺点:
-
第一,调用参数过多。dsn参数指定文件夹路径,layer参数指定文件名,且不带拓展名;
-
第二,可以读取包含中文字符的文件,但是要调用额外的参数。首先需要将use_iconv参数设置为TRUE,再设置encoding参数为UTF-8;
-
第三,运行速度相比
st_read()
函数慢得多。
1.3 st_read()
library(sf)
sf11 <- st_read("G:/北卡罗来纳州.shp")
sf12 <- st_read("G:/nc2.shp")
sf13 <- st_read("G:/nc.shp")
class(sf13)
# 部分输出结果
> class(sf13)
[1] "sf" "data.frame"
可以看出,st_read()
函数相比于另外两个函数调用格式简单地多,运行速度也更快。
st_read()
在sf
工具包中还有一个别名函数read_sf()
,其使用方式与st_read()
差不多,主要区别是它读取数据后以tibble格式储存。
library(sf)
sf21 <- read_sf("G:/北卡罗来纳州.shp")
sf22 <- read_sf("G:/nc2.shp")
sf23 <- read_sf("G:/nc.shp")
class(sf23)
# 部分输出结果
> class(sf23)
[1] "sf" "tbl_df" "tbl" "data.frame"
2 两种数据格式的转换
sf格式数据具有简洁、易于理解等诸多优点,已经被广泛使用。然而,目前R中的许多空间处理方法仍然只能针对sp格式的数据进行操作,因此有时需要进行两种数据格式的转换。具体方法见以下代码:
library(sf)
world <- spData::world # 样本数据
class(world)
# From sf to sp
# 方法1:使用基础包中的as函数
sp.01 <- as(world, "Spatial")
class(sp.01)
# 方法2:使用sf包中的as_Spatial函数
sp.02 <- as_Spatial(world)
class(sp.02)
# From sp to sf
# 方法1:使用基础包中的as函数
sf.01 <- as(sp.01, "sf")
class(sf.01)
# 方法2:使用sf包中的st_as_sf函数
sf.02 <- st_as_sf(sp.01)
class(sf.02)
3 保存数据到本地
如果要将空间矢量数据以shp格式保存在本地,可以使用sf
中的st_write()
函数或它的别名函数wrtite_sf()
。
st_write(world, "G:/world.shp")
write_sf(world, "G:/world2.shp")
需要注意的是,st_write()
在保存前需要将该文件夹下的同名文件删掉或重命名,否则会报错;或者设置参数delete_layer为TRUE:
st_write(world, "G:/world.shp", delete_layer = TRUE)
write_sf
的该参数默认为TRUE,无需修改。