【问题标题】:Plot outline around raster cells在栅格单元周围绘制轮廓
【发布时间】:2016-01-13 01:10:19
【问题描述】:

使用 ggplot2 我想绘制一个多边形(凸包?),它尊重光栅图的单元边界(使用geom_raster 创建)。我可以使用凸包方法,但它们会通过 x-y 坐标而不是光栅图的单元格周围(抱歉,我的术语受我的无知影响)。例如,给定以下具有分类属性d的x-y坐标数据:

df <- data.frame(x = c(295, 300, 305, 310, 295, 300, 305, 310),
                 y = c(310, 310, 310, 310, 315, 315, 315, 315),
                 d = c(2, 2, 2, 1, 2, 1, 1, 1))

我可以使用 ggplot2 的 geom_raster 将属性绘制为填充:

ggplot(df, aes(x, y)) +
  geom_raster(aes(fill = d)) +
  coord_fixed()

给予:

但我想要的是d 定义的类别的轮廓外壳。像这样的:

我可以使用基本 R 和 ggplot2 来做到这一点,还是有办法使用 raster 包或其他一些网格/栅格/GIS 包?我更喜欢让它尽可能简单。

【问题讨论】:

    标签: r ggplot2


    【解决方案1】:

    您当然可以使用 R 的空间设施获得这些多边形。这是一种方法:

    library(raster)
    
    ## Convert your data.frame to a raster object
    r <- rasterFromXYZ(df)
    
    ## Extract polygons
    pp <- rasterToPolygons(r, dissolve=TRUE)
    
    ## Convert SpatialPolygons to a format usable by ggplot2
    outline <- fortify(pp)
    
    ## Put it all together:
    ggplot(df, aes(x, y)) +
        geom_raster(aes(fill = d)) +
        coord_fixed() +
        geom_path(aes(x = long, y = lat, group = group), data = outline, 
                  size=1.5, col="gold")
    

    【讨论】:

    • 这行得通,但对我来说只是其中的一部分。有没有办法将多边形对象用作 ggplot2 中的图层?也许是另一个光栅包转换例程?
    • @AlexT 尝试,例如,执行obj &lt;- fortify(pp),然后将其附加到您示例中的ggplot() 调用:geom_path(aes(x = long, y = lat, group = group), data = obj)。它可以工作,即使我猜这不是 ggplot2 用户会怎么做...
    • 效果很好。我似乎必须加载 maptools 包才能使 fortify 工作。我可以将整个转换组合在一个 dplyr 字符串中,这使它变得美观且可读:outline &lt;- df %&gt;% rasterFromXYZ() %&gt;% rasterToPolygons(dissolve = TRUE) %&gt;% fortify(region = "d")
    • 感谢您使用fortify 步骤更新您的答案。
    【解决方案2】:

    不幸的是,包作者不再推荐来自 {ggplot2} 的fortify()那些包作者也不再推荐来自 {broom} 包的建议替换 tidy()

    幸运的是,我们可以使用 {sf} 包重新创建 Josh O'Brien 的答案。我们仍然依赖 {raster} 包中的一些功能,但一旦修复了假定的错误,这些功能可能可以用 {stars} 包替换(请参阅https://github.com/r-spatial/sf/issues/1389)。如果您的栅格非常大,使用 {stars} 可能会有优势,因为将栅格(或数据框)转换为连续的多边形可能非常慢(请参阅https://gis.stackexchange.com/a/313550/114075)。

    这是代码(借用 Josh O'Brien 的设置):

    library(raster)
    library(rgeos)
    library(ggplot2)
    library(sf)
    
    df <- data.frame(x = c(295, 300, 305, 310, 295, 300, 305, 310),
                     y = c(310, 310, 310, 310, 315, 315, 315, 315),
                     d = c(2, 2, 2, 1, 2, 1, 1, 1))
    
    ## Convert your data.frame to a raster object
    r <- raster::rasterFromXYZ(df)
    
    ## Extract polygons
    pp <- raster::rasterToPolygons(r, dissolve = TRUE)
    
    ## Convert SpatialPolygons to a format usable by ggplot2
    outline <- sf::st_as_sf(pp)
    
    ## Put it all together:
    ## The polygon "outline" is filled by default so will cover up the
    ## raster values. Use fill = NA for the geom_sf() to just use the
    ## gold border color. 
    ggplot(df) +
      geom_raster(aes(x = x, y = y, fill = d)) +
      geom_sf(data = outline, size = 1.5, col = "gold", fill = NA)
    

    或者,将sf 对象转换为LINESTRING,则无需在对geom_sf() 的调用中使用fill = NA 参数:

    library(raster)
    library(rgeos)
    library(ggplot2)
    library(sf)
    
    df <- data.frame(x = c(295, 300, 305, 310, 295, 300, 305, 310),
                     y = c(310, 310, 310, 310, 315, 315, 315, 315),
                     d = c(2, 2, 2, 1, 2, 1, 1, 1))
    
    ## Convert your data.frame to a raster object
    r <- raster::rasterFromXYZ(df)
    
    ## Extract polygons
    pp <- raster::rasterToPolygons(r, dissolve = TRUE)
    
    ## Or you can cast to a linestring instead of using a polygon
    ## and then having to use the fill = NA argument in the 
    ## geom_sf() call
    outline <- sf::st_as_sf(pp) %>% st_cast("LINESTRING")
    
    ggplot(df) +
      geom_raster(aes(x = x, y = y, fill = d)) +
      geom_sf(data = outline, size = 1.5, col = "gold")
    

    【讨论】:

      猜你喜欢
      • 2018-08-30
      • 2016-11-20
      • 2012-09-05
      • 2018-02-13
      • 2019-11-04
      • 1970-01-01
      • 1970-01-01
      • 2013-01-03
      相关资源
      最近更新 更多