如何在ggplot2中显示多层shapefile中的嵌套多边形?
嘿,这个问题我之前帮人排查过——核心原因是你用的fortify()函数在转换空间多边形时,把原本的拓扑信息(比如多边形的内外环)给弄丢了,导致ggplot没法识别那些“孔洞”其实是嵌套的内环,直接给填起来了。下面给你最靠谱的解决办法:
解决嵌套多边形显示问题的方案
优先推荐:用sf包替代老旧的sp+fortify工作流
现在R处理空间数据的标准工具是sf包,它原生支持shapefile的拓扑结构,能完美识别嵌套的内外环,根本不需要fortify()这种容易丢信息的转换步骤。
完整可运行代码
# 先加载依赖包 library(sf) library(ggplot2) # 读取shapefile,sf直接支持,不用再用readShapePoly Thailand <- st_read("Thailand.shp") Bthy_200m <- st_read("ne_10m_bathymetry_K_200.shp") Bthy_1000m <- st_read("ne_10m_bathymetry_all/ne_10m_bathymetry_J_1000.shp") Bthy_2000m <- st_read("ne_10m_bathymetry_all/ne_10m_bathymetry_I_2000.shp") # 定义裁剪范围,转换成sf的空间对象 crop_bbox <- st_bbox(c( xmin = 84.11236, xmax = 108.4594, ymin = -4.046979, ymax = 24.09534 )) %>% st_as_sfc() # 裁剪数据,sf的st_crop比sp的crop更稳定 Bthy_200m_crop <- st_crop(Bthy_200m, crop_bbox) Bthy_1000m_crop <- st_crop(Bthy_1000m, crop_bbox) Bthy_2000m_crop <- st_crop(Bthy_2000m, crop_bbox) # 绘制地图,geom_sf自动处理嵌套多边形! ggplot() + # 先设置主题样式 theme_bw() + theme( panel.background = element_rect(fill = "#5EA8A7"), panel.grid.major = element_blank(), panel.grid.minor = element_blank() ) + # 注意绘制顺序:从最深的到最浅的,这样层级才对 geom_sf(data = Bthy_2000m_crop, fill = "#004D47", color = NA) + geom_sf(data = Bthy_1000m_crop, fill = "#128277", color = NA) + geom_sf(data = Bthy_200m_crop, fill = "#52958b", color = NA) + # 叠加陆地多边形 geom_sf(data = Thailand, fill = "#99CCCC", color = "black")
为什么这个方法能解决问题?
sf包会完整保留shapefile里的拓扑属性——比如多边形的外环是顺时针,内环是逆时针(或者反过来),geom_sf会根据这个方向自动判断哪些是需要留空的“孔洞”,不会像geom_polygon那样把所有环都当成要填充的区域。而你原来用的fortify()函数,会把所有环都拆成普通的group,ggplot根本分不清哪个是内环,自然就把孔洞填满了。
备选方案:修复sp+fortify的数据集(不推荐,太麻烦)
如果非要坚持用原来的sp框架,你得手动去判断每个group的环方向(比如计算多边形面积,内环的面积会是负数),然后给内环设置fill=NA,但这个步骤非常繁琐,很容易出错,而且后期维护起来也麻烦,真心不如直接切换到sf包。
内容的提问来源于stack exchange,提问作者Young
相关产品推荐
相关产品推荐

