比较简单要素{sf}和空间对象{sp}:速度和记忆

Hug*_*ugo 5 intersection r r-sp r-sf

我在R中使用了一些空间数据,并想知道是否使用依赖于旧的Spatial格式(包sp)或新包sf的包/函数.我根据此处的代码进行了此测试.

该想法是"识别相对于空间点数据集中的每个单独点落入xx米的最大距离内的所有点".

library(tictoc)

# define a buffer distance and a toy data
maxdist <- 500
df<-data.frame(x = runif(10000, 0, 100000),y = runif(10000, 0, 100000),id = 1:10000)

# doing the analysis using sf
library(sf)
tic("sf")
pts     <- df %>% st_as_sf(coords = c("x", "y"))
pts_buf <- st_buffer(pts, maxdist,nQuadSegs = 5)
int     <- st_intersects(pts_buf, pts)
toc()

# doing the analysis using sp
library(sp)
library(rgeos)
tic("sp")
pts2      <- SpatialPointsDataFrame(df[,1:2],as.data.frame(df[,3]))
pts_buf2  <- gBuffer(pts2, byid=TRUE,width=maxdist)
int2      <- over(pts_buf2, pts2,returnList = TRUE)
toc()

# size of the objects
object.size(pts)<object.size(pts2)
object.size(pts_buf)<object.size(pts_buf2)
Run Code Online (Sandbox Code Playgroud)

使用sf似乎要好得多(在我的机器中大约0.53 vs 2.1秒)并且需要更少的内存.但有一个例外.为什么对象pts远大于pts2?在存储点矢量时,sf效率较低吗?

Sym*_*xAU 4

我能想到的一个原因是:

pts( )对象保留一个属性,指定每一行sf的几何对象的“类型” 。这是因为每一行都有可能成为对象中不同的几何图形。sf

pts2( sp) 位于类的对象中SpatialPointsDataFrame。它只能保存点,因此不需要为每个“行”保留额外的属性

以对象的前两行为sf例,这些是与这些几何图形关联的属性

lapply(1:2, function(x) attributes(st_geometry(pts[x, ])))
# [[1]]
# [[1]]$names
# [1] "1"
# 
# [[1]]$class
# [1] "sfc_POINT" "sfc"      
# 
# [[1]]$precision
# [1] 0
# 
# [[1]]$bbox
# xmin     ymin     xmax     ymax 
# 81647.16 72283.90 81647.16 72283.90 
# 
# [[1]]$crs
# Coordinate Reference System: NA
# 
# [[1]]$n_empty
# [1] 0
# 
# 
# [[2]]
# [[2]]$names
# [1] "2"
# 
# [[2]]$class
# [1] "sfc_POINT" "sfc"      
# 
# [[2]]$precision
# [1] 0
# 
# [[2]]$bbox
# xmin      ymin      xmax      ymax 
# 5591.116 38967.060  5591.116 38967.060 
# 
# [[2]]$crs
# Coordinate Reference System: NA
# 
# [[2]]$n_empty
# [1] 0
Run Code Online (Sandbox Code Playgroud)

该 data.frame 的每一行都sf具有相似的属性。

如果您从几何图形中删除属性(仅留下 data.frame)

pts_coords <- st_coordinates(pts)
pts_striped <- pts
st_geometry(pts_striped) <- NULL
pts_striped <- cbind(pts_striped, pts_coords)
Run Code Online (Sandbox Code Playgroud)

然后比较物体大小

object.size(pts_striped)
# 200896
object.size(pts2)
# 203624
Run Code Online (Sandbox Code Playgroud)

物体的尺寸更加接近