如何用ggplot2或levelplot生成ArcGIS风格的独立地图图例
嘿,我来帮你搞定这个需求!下面分别用ggplot2和levelplot两种工具实现流域名称替换+ArcGIS风格独立图例,直接上可运行的代码和解释:
先准备样本数据
首先模拟一组流域空间数据,包含原始名称、要替换的新名称,以及用于着色的数值字段:
# 加载所需包 library(sf) library(ggplot2) library(rasterVis) library(cowplot) # 用于组合独立图例(可选) # 模拟流域多边形数据 watersheds <- st_sfc( st_polygon(list(rbind(c(0,0), c(0,2), c(2,2), c(2,0), c(0,0)))), st_polygon(list(rbind(c(2,0), c(2,2), c(4,2), c(4,0), c(2,0)))), st_polygon(list(rbind(c(0,2), c(0,4), c(2,4), c(2,2), c(0,2)))), st_polygon(list(rbind(c(2,2), c(2,4), c(4,4), c(4,2), c(2,2)))) ) %>% st_sf( id = 1:4, old_name = c("流域A", "流域B", "流域C", "流域D"), new_name = c("长江上游", "长江中游", "黄河上游", "黄河中游"), # 替换后的新名称 value = c(10, 25, 18, 32) # 用于地图着色的数值 )
方法一:用ggplot2实现
核心操作:
- 替换流域名称:直接调用
geom_sf_text()指定新名称字段 - 生成ArcGIS风格独立图例:通过
guides()和theme()调整图例的边框、背景、位置,模拟ArcGIS的悬浮图例效果
# ggplot2绘图代码 ggplot() + # 绘制流域多边形 geom_sf(data = watersheds, aes(fill = value), color = "black", linewidth = 0.8) + # 替换为新的流域名称标注(白色粗体更醒目) geom_sf_text(data = watersheds, aes(label = new_name), color = "white", size = 4, fontface = "bold") + # 设置渐变配色(可选替换为ArcGIS常用配色) scale_fill_viridis_c(option = "viridis", name = "流域指数") + # 调整图例样式:添加边框、刻度,设置标题位置 guides(fill = guide_colorbar( title.position = "top", title.hjust = 0.5, barwidth = 15, barheight = 1, frame.colour = "black", ticks.colour = "black" )) + # 调整主题,适配地图风格 theme_minimal() + theme( legend.position = "bottom", # 可改为"right"/"left"自定义位置 legend.box = "horizontal", legend.background = element_rect(fill = "white", color = "black"), # 图例白色背景+黑色边框 legend.margin = margin(5,5,5,5), plot.title = element_text(hjust = 0.5, size = 14, face = "bold"), axis.text = element_blank(), # 隐藏坐标轴文字 axis.ticks = element_blank() # 隐藏坐标轴刻度 ) + labs(title = "流域分布图(替换名称+ArcGIS风格图例)")
进阶:完全独立的图例
如果想要图例和绘图区域完全分开(和ArcGIS布局一致),可以用cowplot包提取图例后组合:
# 先绘制不带图例的地图 p_map <- ggplot() + geom_sf(data = watersheds, aes(fill = value), color = "black", linewidth = 0.8) + geom_sf_text(data = watersheds, aes(label = new_name), color = "white", size = 4, fontface = "bold") + scale_fill_viridis_c(option = "viridis", name = "流域指数") + theme_minimal() + theme( legend.position = "none", # 隐藏图例 plot.title = element_text(hjust = 0.5, size = 14, face = "bold"), axis.text = element_blank(), axis.ticks = element_blank() ) + labs(title = "流域分布图") # 单独生成图例 p_legend <- cowplot::get_legend( ggplot() + geom_sf(data = watersheds, aes(fill = value)) + scale_fill_viridis_c(option = "viridis", name = "流域指数") + guides(fill = guide_colorbar( title.position = "top", title.hjust = 0.5, barwidth = 15, barheight = 1, frame.colour = "black", ticks.colour = "black" )) + theme( legend.background = element_rect(fill = "white", color = "black"), legend.margin = margin(5,5,5,5) ) ) # 组合地图和图例 cowplot::plot_grid(p_map, p_legend, ncol = 1, rel_heights = c(4, 1))
方法二:用levelplot(rasterVis包)实现
levelplot适合处理栅格数据,也可以兼容矢量数据(需转换为sp对象),核心操作类似:
# 转换sf对象为sp对象(适配levelplot) watersheds_sp <- as(watersheds, "Spatial") # levelplot绘图代码 levelplot(value ~ 1, data = watersheds_sp, col.regions = viridis::viridis(100), # 渐变配色 main = list(label = "流域分布图(替换名称+ArcGIS风格图例)", cex = 1.2), # 设置ArcGIS风格图例 colorkey = list( space = "bottom", # 图例位置 width = 0.8, height = 0.1, box = list(col = "black"), # 图例边框 axis.line = list(col = "black"), # 刻度线 labels = list(cex = 0.8), title = list(label = "流域指数", cex = 0.9, font = 2) ), # 隐藏坐标轴 scales = list(draw = FALSE), # 自定义面板,添加替换后的流域名称标注 panel = function(x, y, ...) { panel.levelplot(x, y, ...) # 获取每个流域的中心点坐标 coords <- coordinates(watersheds_sp) # 添加新名称标注(白色粗体) text(coords[,1], coords[,2], labels = watersheds_sp$new_name, col = "white", font = 2, cex = 0.9) })
一些实用提示
- 配色可以替换为ArcGIS常用的配色,比如用
RColorBrewer包的brewer.pal()函数; - 如果原始数据是栅格,levelplot可以直接读取栅格对象,标注可以通过提取流域边界的中心点坐标实现;
- 标注位置可以根据实际流域形状调整,比如用
st_centroid()计算更准确的中心点。
内容的提问来源于stack exchange,提问作者code123
相关产品推荐
相关产品推荐

