【问题标题】:How to clip WorldMap with polygon in R?如何在 R 中用多边形剪辑 WorldMap?
【发布时间】:2013-03-30 16:10:28
【问题描述】:

我使用 R 包栅格从 www.GADM.org 导入了世界地图数据集。我想将它剪辑到我创建的多边形以减小地图的大小。我可以检索数据并且可以创建多边形没问题,但是当我使用“gIntersection”命令时,我收到一条模糊的错误消息。

关于如何剪辑我的世界地图数据集有什么建议吗?

library(raster)
library(rgeos)

## Download Map of the World ##
WorldMap <- getData('countries')

## Create the clipping polygon
clip.extent <- as(extent(-20, 40, 30, 72), "SpatialPolygons")
proj4string(clip.extent) <- CRS(proj4string(WorldMap))

## Clip the map
EuropeMap <- gIntersection(WorldMap, clip.extent, byid = TRUE)

错误信息:

RGEOSBinTopoFunc(spgeom1, spgeom2, byid, id, "rgeos_intersection") 中的错误: 几何集合可能不包含其他几何集合 另外:警告信息: 在 RGEOSBinTopoFunc(spgeom1, spgeom2, byid, id, "rgeos_intersection") 中: spgeom1 和 spgeom2 有不同的 proj4 字符串

【问题讨论】:

    标签: r gis polygon crop clip


    【解决方案1】:

    您不需要使用 PBS(我已经学会了这一点,因为@flowla 发布的r-sig-geo 链接是我最初发布的问题!)。这段代码展示了如何在 rgeos 中完成这一切,感谢来自 Roger Bivand 的 various 不同的 postings。这将是更规范的子集化方式,无需强制转换为 PolySet 对象。

    错误消息的原因是您不能在 SpatialPolygons 集合上 gIntersection,您需要单独执行它们。使用gIntersects 找出您想要的。然后我使用gIntersection 对每个国家多边形进行子集化。我在将 SpatialPolygons 对象列表传递回 SpatialPolygons 时遇到问题,这会将裁剪后的 shapefile 转换为 SpatialPolygons,这是因为并非所有裁剪后的对象都属于 classSpatialPolygons。一旦我们排除了这些,一切正常。

    # This very quick method keeps whole countries
    gI <- gIntersects(WorldMap, clip.extent, byid = TRUE )
    Europe <- WorldMap[which(gI), ]
    plot(Europe)
    
    
    #If you want to crop the country boundaries, it's slightly more involved:
    # This crops countries to your bounding box
    gI <- gIntersects(WorldMap, clip.extent, byid = TRUE)
    out <- lapply(which(gI), function(x){ 
            gIntersection(WorldMap[x,], clip.extent)
       })
    
    # But let's look at what is returned
    table(sapply(out, class))
    #   SpatialCollections    SpatialPolygons 
    #                    2                 63 
    
    
    # We want to keep only objects of class SpatialPolygons                 
    keep <- sapply(out, class)
    out <- out[keep == "SpatialPolygons"]
    
    
    # Coerce list back to SpatialPolygons object
    Europe <- SpatialPolygons(lapply(1:length(out), function(i) {
              Pol <- slot(out[[i]], "polygons")[[1]]
              slot(Pol, "ID") <- as.character(i)
              Pol
       }))
    
    plot(Europe)
    

    如果可以,我建议您查看naturalearthdata。他们拥有高质量的 shapefile,这些文件会保持最新状态,并且会不断检查错误(因为它们是开源的,如果您发现错误,请通过电子邮件发送给他们)。国家/地区边界位于文化按钮下方。您会发现它们也更轻量级,您可以选择适合您需要的分辨率。

    【讨论】:

    • 这太棒了!我仍然不确定我是否理解子集化为什么有效。我将一个多边形与一个多边形网格相交(基本上将网格裁剪到边界)——如果单元格足够大,则不需要子集,但如果单元格很小,则会发生所描述的错误。为什么gIntersection(grid[gIntersects(grid, poly, byid = TRUE), ], poly, byid = TRUE) 可以工作,而普通的gIntersection(grid, poly, byid = TRUE) 不行?
    • 我无法重现该示例,因为 getData('countries') 不起作用,因此将其作为注释:如果 Simon 描述的例程由于未达到最佳复杂形状文件而丢弃了一些多边形,请尝试 @987654334 @。这为我解决了一个类似的错误,并且没有丢弃不需要的多边形。
    【解决方案2】:

    中间的小步骤怎么样?我主要从R-sig-Geo 采用了以下代码,我认为它应该可以解决问题。您将需要“maptools”和“PBSmapping”软件包,因此请确保已安装它们。这是我的代码:

    # Required packages
    library(raster)
    library(maptools)
    library(PBSmapping)
    
    # Download world map
    WorldMap <- getData('countries')
    # Convert SpatialPolygons to class 'PolySet'
    WorldMap.ps <- SpatialPolygons2PolySet(WorldMap)
    # Clip 'PolySet' by given extent
    WorldMap.ps.clipped <- clipPolys(WorldMap.ps, xlim = c(-20, 40), ylim = c(30, 72))
    # Convert clipped 'PolySet' back to SpatialPolygons
    EuropeMap <- PolySet2SpatialPolygons(WorldMap.ps.clipped, close_polys=TRUE)
    

    我刚刚对其进行了测试,它可以正常工作。不过,将 SpatialPolygons 转换为 PolySet 需要一些计算时间。

    干杯, 弗洛里安

    【讨论】:

    • 这很好用,但由于某种原因,当你绘制它时,我在所需区域周围得到了很大的区域(来自上面的代码)。即使我使用:'plot(EuropeMap, xlim=c(-20,40), ylim=c(30,72))'
    • 您有任何需要地图的进一步处理步骤,还是只是为了绘制欧洲?在后一种情况下,我建议使用“PBSmapping”包中的plotMap(WorldMap.ps.clipped)。它生成了一张非常漂亮的地图,左右两边没有任何令人不安的空白。
    猜你喜欢
    • 1970-01-01
    • 2015-10-01
    • 1970-01-01
    • 2020-09-22
    • 1970-01-01
    • 1970-01-01
    • 2021-03-10
    • 2015-05-02
    • 2021-11-20
    相关资源
    最近更新 更多