【问题标题】:Quickest way to crop/clip a complex SpatialPolygonsDataFrame using another polygon使用另一个多边形裁剪/剪辑复杂 SpatialPolygonsDataFrame 的最快方法
【发布时间】:2020-07-26 06:30:56
【问题描述】:

使用另一个可能很复杂的 SpatialPolygon 裁剪(裁剪)复杂的 SpatialPolygonsDataFrame 的最快方法是什么?我知道两种方法(如下所示)。 raster 方式对于不太复杂的 SpatialPolygonsDataFrames 更快,并返回一个 SpatialPolygonsDataFrame,如示例中所示。但是,大型 SpatialPolygonsDataFrames 会变慢。 rgeos 方式对于大型 SpatialPolygonsDataFrame 更快,但 it sometimes fails with very complex geometries 并且默认不返回 SpatialPolygonsDataFrames。

我最近没有关注 R 中的 GIS 开发,现在可能有更快的方法来做这件事。

示例多边形很小,以尊重人们的计算机和带宽。考虑 50-1000 MB 的“真实”多边形。

设置:

library(rnaturalearth)
library(sp)
library(raster)
library(rgeos)

dt <- rnaturalearth::ne_countries()
clip_boundary <- sp::SpatialPolygons(list(sp::Polygons(
list(sp::Polygon(data.frame(lon = c(0, 180, 180, 0), lat = c(40, 40, 80, 80)))), ID = 1)))

rgeos 方式:

system.time({
clipped.dt <- rgeos::gIntersection(dt, clip_boundary, byid = TRUE)
ids <- sapply(slot(clipped.dt, "polygons"), function(x) slot(x, "ID"))
ids <- sapply(strsplit(ids, " "), "[", 1) 

tmp.df <- data.frame(dt@data[ids,])
names(tmp.df) <- names(dt@data)

out <- sp::SpatialPolygonsDataFrame(clipped.dt, tmp.df, match.ID = FALSE)
})

#   user  system elapsed 
#  0.069   0.002   0.074 

class(out)
# [1] "SpatialPolygonsDataFrame"
# attr(,"package")
# [1] "sp"

raster 方式:

system.time({
  out <- raster::crop(dt, clip_boundary)
})

#   user  system elapsed 
#  0.042   0.001   0.043 

class(out)
# [1] "SpatialPolygonsDataFrame"
# attr(,"package")
# [1] "sp"

参考图(与问题无关):

plot(out)

【问题讨论】:

    标签: r performance gis spatial r-raster


    【解决方案1】:

    现在可以使用 sf 包完成 R 的大部分地理空间工作。

    https://r-spatial.github.io/sf/index.html

    看起来它可能比光栅和 sp 快一点。

    library(rnaturalearth)
    library(sp)
    #library(raster)
    #library(rgeos)
    library(sf)
    #> Linking to GEOS 3.7.2, GDAL 2.4.2, PROJ 5.2.0
    library(ggplot2)
    
    # Original data 
    dt <- rnaturalearth::ne_countries()
    clip_boundary <- sp::SpatialPolygons(list(sp::Polygons(
      list(sp::Polygon(data.frame(lon = c(0, 180, 180, 0), lat = c(40, 40, 80, 80)))), ID = 1)))
    
    # Original data as sf objects
    dt_sf <- st_as_sf(dt)
    boundary_sf <- st_as_sf(clip_boundary)
    
    # clip 
    clipped <- st_crop(dt_sf, boundary_sf)
    #> although coordinates are longitude/latitude, st_intersection assumes that they are planar
    #> Warning: attribute variables are assumed to be spatially constant throughout all
    #> geometries
    
    #plot
    ggplot(clipped) + geom_sf()
    

    
    system.time({
      out <- st_crop(dt_sf, boundary_sf)
    })
    #> although coordinates are longitude/latitude, st_intersection assumes that they are planar
    #> Warning: attribute variables are assumed to be spatially constant throughout all
    #> geometries
    #>    user  system elapsed 
    #>   0.019   0.000   0.018
    
    system.time({
      out <- raster::crop(dt, clip_boundary)
    })
    #> Warning in raster::crop(dt, clip_boundary): non identical CRS
    #>    user  system elapsed 
    #>   0.526   0.000   0.525
    
    system.time({
      clipped.dt <- rgeos::gIntersection(dt, clip_boundary, byid = TRUE)
      ids <- sapply(slot(clipped.dt, "polygons"), function(x) slot(x, "ID"))
      ids <- sapply(strsplit(ids, " "), "[", 1) 
    
      tmp.df <- data.frame(dt@data[ids,])
      names(tmp.df) <- names(dt@data)
    
      out <- sp::SpatialPolygonsDataFrame(clipped.dt, tmp.df, match.ID = FALSE)
    })
    #> Warning in RGEOSBinTopoFunc(spgeom1, spgeom2, byid, id, drop_lower_td,
    #> unaryUnion_if_byid_false, : spgeom1 and spgeom2 have different proj4 strings
    #>    user  system elapsed 
    #>   0.045   0.000   0.045
    

    reprex package (v0.3.0) 于 2020 年 4 月 13 日创建

    【讨论】:

    • 感谢您指出sf 包。我没想到。在我使用裁剪的应用程序中,形状必须以sp 格式返回。转换使sf 解决方案比rgeos 解决方案稍慢(我拥有的一个数据集的系统时间:rgeos ~ 7 秒,sf ~ 9 秒和raster > 80 秒)。但是,如果您已经使用 sf 对象进行操作,那么您的建议可能是迄今为止最快的。在接受您的回答之前,我会将问题留待一段时间。也许有人想出了一个我们没有想到的更快的解决方案。
    • sp -> sf -> sp 会减慢速度。我没有意识到 sp 是您的要求。 R 通常不是很快,但你总是可以把更大的电脑扔给它。我发现sf 进行空间操作的方式确实比sp 直观得多。祝你好运。
    猜你喜欢
    • 1970-01-01
    • 2012-12-08
    • 1970-01-01
    • 2017-10-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-04
    • 1970-01-01
    相关资源
    最近更新 更多