在ggplot绘制的撒丁岛地图中添加自定义图例的技术问题
解决ggplot2绘制撒丁岛地图的自定义图例问题
使用ggplot2绘制包含意大利NUTS2、NUTS3边界、研究网格及大气模拟起始点的撒丁岛地图时,无法添加符合需求的自定义图例(要求:蓝色实线=NUTS2边界、棕色实线=NUTS3边界、黑色虚线=研究网格、红色点=模拟起始点)。尝试混用base R的legend()函数时,出现错误:Error: (converted from warning) Duplicated aesthetics after name standardisation: fontface。
错误原因分析
- 绘图系统不兼容:ggplot2基于网格系统,不能直接与base R的绘图函数(如
legend())混用,强行拼接会导致渲染冲突。 - 重复美学参数:代码中
annotate()部分重复设置了fontface参数(同时写了fontface = "italic"和fontface = "bold"),这是触发报错的直接原因。
解决方案:用ggplot2原生方式构建统一图例
以下是修正后的完整代码,通过ggplot2的美学映射和虚拟图层实现自定义图例:
# 加载所需包 library(giscoR) library(sf) library(ggplot2) library(ggspatial) # 获取意大利NUTS2和NUTS3区域 nuts2_italy <- gisco_get_nuts(year="2021", nuts_level = 2, country = "Italy") sardinia_nuts2 <- nuts2_italy[nuts2_italy$NUTS_NAME=='Sardegna',] nuts3_italy <- gisco_get_nuts(year="2021", nuts_level = 3, country = "Italy") # 加载模拟起始点 start_pt <- st_read("data/HYSPLIT_start_points/start_points.shp") # 构建地图 map <- ggplot() + # NUTS3边界:映射颜色到图例 geom_sf(data=nuts3_italy, fill = "antiquewhite", aes(color = "NUTS3 borders"), show.legend = "line") + # NUTS2边界:映射颜色到图例 geom_sf(data=sardinia_nuts2, fill = NA, aes(color = "NUTS2 border"), show.legend = "line") + # 模拟起始点:映射颜色到图例 geom_sf(data=start_pt, aes(color = "Initiation points"), size=1) + # 研究网格虚拟图层:用于生成图例项 geom_sf(data = sardinia_nuts2, fill = NA, color = NA, aes(linetype = "study grid"), show.legend = "line") + # 设置坐标范围 coord_sf(xlim = c(7.5, 10.5), ylim = c(38.7, 41.3), expand = TRUE) + # 比例尺和指北针 annotation_scale(location = "bl", width_hint = 0.5, text_family = "serif", bar_cols = c("#887e6a", "#fffff3")) + annotation_north_arrow(location = "br", which_north = "true", pad_x = unit(0.75, "cm"), pad_y = unit(0.2, "cm"), style = north_arrow_fancy_orienteering( fill = c("#887e6a", "#fffff3"), line_col = "#887e6a", text_family = "serif" )) + # 修复重复fontface问题:合并为italic.bold annotate(geom = "text", x = 9, y = 40.7, label = "Sardinia", fontface = "italic.bold", size = 5, family = "serif", color="#887e6a") + # 定义图例颜色映射 scale_color_manual( name = "", values = c( "NUTS2 border" = "blue", "NUTS3 borders" = "#887e6a", "Initiation points" = "red" ), guide = guide_legend(order = 1) ) + # 定义图例线型映射 scale_linetype_manual( name = "", values = c("study grid" = "dashed"), guide = guide_legend(order = 2) ) + # 坐标轴标签 labs(x="Longitude", y="Latitude") + # 主题设置 theme( panel.grid.major = element_line(color = gray(.5), linetype = "dashed", size = 0.5), panel.background = element_rect(fill = "aliceblue"), panel.border = element_rect(colour = "#887e6a", fill = NA, size = 1.5), axis.text = element_text(family = "serif", colour = "#887e6a"), legend.position = "topright", legend.text = element_text(family = "serif") ) # 显示地图 map
关键调整说明
- 修复
annotate()中重复的fontface参数,改为fontface = "italic.bold"。 - 为每个需要图例的图层添加
aes()映射,通过scale_color_manual和scale_linetype_manual统一控制图例样式与标签。 - 添加虚拟
geom_sf图层,解决研究网格(theme元素)无法直接加入图例的问题。 - 移除base R的
legend()函数,完全使用ggplot2原生逻辑构建图例,避免系统冲突。
内容的提问来源于stack exchange,提问作者abibard
相关产品推荐
相关产品推荐

