如何使用ggplot绘制区域边界?——R语言
解决ggplot绘制区域轮廓时geom_contour插值多余线条的问题
问题背景
你在数据集里定义了带分组标识的空间点,数据集预览如下:
head(regions_gg)
lon lat group
12 -69.75 -19.75 3
13 -69.25 -19.75 3
14 -68.75 -19.75 3
15 -68.25 -19.75 3
16 -67.75 -19.75 3
17 -67.25 -19.75 3
每个空间点通过group字段归属到对应区域,你尝试用以下代码绘制区域轮廓,但geom_contour()的插值操作生成了大量多余线条:
ggplot(regions_gg,aes(x=lon,y=lat,fill=group,z=group))+theme_bw()+ geom_raster(interpolate=F)+geom_contour()
解决方案
嘿,太懂这种被多余插值线条搞崩的感觉了!geom_contour()天生是用来处理连续数据的,对你这种已经按group离散分组的栅格数据来说,完全是用错了工具。给你几个简单直接的替代方案:
方案1:提取区域轮廓多边形(最稳定通用)
这种方法会直接基于每个group的点生成真实的区域边界,完全不会有插值问题。分两种情况处理:
情况A:区域是凸形(用基础包+dplyr)
如果你的区域都是凸形状,用chull()函数提取凸包顶点就能快速生成轮廓:
library(dplyr) library(tidyr) # 提取每个group的凸包顶点 region_polygons <- regions_gg %>% group_by(group) %>% summarise(lon = list(lon), lat = list(lat), .groups = "drop") %>% rowwise() %>% mutate( hull_indices = list(chull(lon, lat)), lon_hull = list(lon[hull_indices]), lat_hull = list(lat[hull_indices]) ) %>% ungroup() %>% select(group, lon_hull, lat_hull) %>% unnest(c(lon_hull, lat_hull)) # 绘制栅格+区域轮廓 ggplot() + theme_bw() + geom_raster(data = regions_gg, aes(x = lon, y = lat, fill = factor(group))) + geom_polygon( data = region_polygons, aes(x = lon_hull, y = lat_hull, color = factor(group)), fill = NA, linewidth = 1 )
情况B:区域非凸形(用sf包处理更准确)
如果你的区域有凹进去的部分,chull()会丢失细节,用sf包的空间处理功能更靠谱:
library(sf) library(dplyr) # 转换为空间点对象 regions_sf <- st_as_sf(regions_gg, coords = c("lon", "lat"), crs = 4326) # 按group合并为区域多边形 region_polygons_sf <- regions_sf %>% group_by(group) %>% summarise() %>% st_union() %>% # 合并同组点 st_cast("POLYGON") # 转换为多边形 # 绘制 ggplot() + theme_bw() + geom_raster(data = regions_gg, aes(x = lon, y = lat, fill = factor(group))) + geom_sf( data = region_polygons_sf, aes(color = factor(group)), fill = NA, linewidth = 1 )
方案2:给栅格块加边界(快速简单)
如果你只是想给每个栅格单元格加边界,不用整体区域轮廓,直接替换geom_raster()为geom_tile()即可:
ggplot(regions_gg, aes(x = lon, y = lat, fill = factor(group))) + theme_bw() + geom_tile(color = "black", size = 0.5) # color参数控制栅格边界的颜色和粗细
方案3:强制geom_contour只按group值生成轮廓(临时救急)
如果你一定要用geom_contour(),可以强制它只识别你的group离散值,避免插值:
ggplot(regions_gg,aes(x=lon,y=lat,fill=factor(group),z=group))+ theme_bw()+ geom_raster(interpolate=F)+ geom_contour( breaks = unique(regions_gg$group), color = "black", linewidth = 1 )
不过这个方法偶尔还是会出现小的插值瑕疵,不如多边形方法稳定。
内容的提问来源于stack exchange,提问作者Eugenia Perez
相关产品推荐
相关产品推荐

