如何为geom_sf绘制的MultiPolygon添加完整图例(支持图层缺失)
问题:为缺失部分图层的GeoJSON数据绘制带完整图例的地图
我从GeoJSON文件读取了MultiPolygon数据:
geojson <- read_sf(filename)
数据如下:
Simple feature collection with 4 features and 1 field Geometry type: MULTIPOLYGON Dimension: XY Bounding box: xmin: -16.64523 ymin: 27.23105 xmax: 39.81916 ymax: 65.99652 Geodetic CRS: WGS 84 # A tibble: 4 × 2 id geometry <chr> <MULTIPOLYGON [°]> 1 Coverage (((-7.599085 33.35191, -7.813386 33.43519, -7.728468 33.51… 2 HighInterference (((30.60789 42.13764, 30.638 42.22092, 30.75046 42.22092, … 3 LowInterference (((24.75786 59.54255, 24.80001 59.62583, 24.96471 59.62583… 4 MediumInterference (((26.36263 58.87633, 26.40755 58.95961, 26.56905 58.95961…
随后我使用geom_sf为每一行数据设置对应颜色绘制:
library("ggplot2") library("sf") library("rnaturalearth") library("rnaturalearthdata") library("ggspatial") library("geojsonR") europe <- ne_countries(scale = "medium", returnclass = "sf") class(europe) filename <- "geojson.geojson" geojson <- read_sf(filename) p <- ggplot() + geom_sf(data = europe) p <- p + geom_sf(data = geojson[geojson$id == "Coverage", ], color = alpha("green", 0.1), fill = alpha("green", 0.1)) p <- p + geom_sf(data = geojson[geojson$id == "LowInterference", ], color = alpha("yellow", 0.5), fill = alpha("yellow", 0.5)) p <- p + geom_sf(data = geojson[geojson$id == "MediumInterference", ], color = alpha("orange", 0.5), fill = alpha("orange", 0.5)) p <- p + geom_sf(data = geojson[geojson$id == "HighInterference", ], color = alpha("red", 0.5), fill = alpha("red", 0.5)) p <- p + coord_sf(xlim = c(-20, 42), ylim = c(33, 72)) plot(p) ggsave(paste(filename, ".pdf", sep = "")) ggsave(paste(filename, ".png", sep = ""))
现在需要给地图添加图例,但GeoJSON文件中并非总是包含所有图层(示例是完整的,但可能缺失任意一个或多个),要求图例始终显示所有可能的取值,不知道该怎么实现。
GeoJSON示例
{ "type": "FeatureCollection", "features": [ { "type": "Feature", "properties": { }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ 0, 40 ], [ 10, 50 ], [ 0, 60 ], [ -10, 55 ], [ 0, 40 ] ] ] ] }, "id": "Coverage" }, { "type": "Feature", "properties": { }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ 20, 45 ], [ 25, 50 ], [ 20, 60 ], [ 0, 50 ], [ 20, 45 ] ] ] ] }, "id": "HighInterference" }, { "type": "Feature", "properties": { }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ 10, 35 ], [ 20, 35 ], [ 20, 40 ], [ 10, 40 ], [ 10, 35 ] ] ] ] }, "id": "LowInterference" }, { "type": "Feature", "properties": { }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ 30, 50 ], [ 40, 50 ], [ 40, 60 ], [ 30, 60 ], [ 30, 50 ] ] ] ] }, "id": "MediumInterference" } ] }
解决方案
要实现图例始终显示所有可能取值,通过因子化类别+手动颜色映射即可完成,具体代码和要点如下:
完整修改代码
library("ggplot2") library("sf") library("rnaturalearth") library("rnaturalearthdata") # 1. 定义所有可能的类别和对应颜色(含透明度) all_categories <- c("Coverage", "LowInterference", "MediumInterference", "HighInterference") color_map <- c( "Coverage" = alpha("green", 0.1), "LowInterference" = alpha("yellow", 0.5), "MediumInterference" = alpha("orange", 0.5), "HighInterference" = alpha("red", 0.5) ) # 读取数据 europe <- ne_countries(scale = "medium", returnclass = "sf") filename <- "geojson.geojson" geojson <- read_sf(filename) # 2. 将id转换为包含所有类别的因子,缺失类别会保留在图例中 geojson$id <- factor(geojson$id, levels = all_categories) # 3. 绘制地图,通过id映射颜色 p <- ggplot() + geom_sf(data = europe) + geom_sf(data = geojson, aes(color = id, fill = id)) + # 手动设置颜色,drop=FALSE强制保留所有类别 scale_color_manual(values = color_map, drop = FALSE) + scale_fill_manual(values = color_map, drop = FALSE) + coord_sf(xlim = c(-20, 42), ylim = c(33, 72)) + labs(color = "类型", fill = "类型") # 自定义图例标题 plot(p) ggsave(paste(filename, ".pdf", sep = "")) ggsave(paste(filename, ".png", sep = ""))
核心要点
- 因子化类别:把
id转为包含所有可能值的因子,确保缺失的类别不会被自动剔除。 - 统一映射颜色:用
aes(color = id, fill = id)替代多次调用geom_sf,代码更简洁且自动关联图例。 - 保留所有图例项:
scale_*_manual中设置drop = FALSE,强制显示所有预定义的类别,哪怕对应数据不存在。
内容的提问来源于stack exchange,提问作者nobody
相关产品推荐
相关产品推荐

