如何在geom_sf中为AREA>0.1的值用Spectral色板,同时展示其他值与NA
问题描述
我希望实现以下地图样式需求:
- AREA大于0.1的空间要素使用RColorBrewer包中的Spectral调色板
- AREA小于0.1的要素设置为深灰色(或填充图案效果)
- NA值渲染为浅灰色
- 确保地图上所有要素都有对应样式
我尝试了两种方法但都没达到预期效果,代码如下:
library(ggnewscale) library(tidyverse) library(sf) nc <- sf::st_read(system.file("shape/nc.shp", package = "sf"), quiet = TRUE) # 添加NA值 nc$AREA[c(1,2,3)] <- NA # 第一种尝试 ggplot(nc) + geom_sf(aes(fill = AREA > 0.1)) + new_scale_fill() + geom_sf(aes(fill = AREA))+ scale_fill_gradientn(colors = RColorBrewer::brewer.pal(9, "Spectral"), na.value = "grey90") # 第二种尝试 remove_col <- "AREA" remove_val <- 0.1 nc %>% filter(.data[[remove_col]] < remove_val) %>% ggplot() + geom_sf(aes(fill = AREA)) + new_scale_fill() + geom_sf(aes(fill = .data[[remove_col]]), color = "black") + scale_fill_gradientn(colors = RColorBrewer::brewer.pal(9, "Spectral"), na.value = "grey90")
解决方案
可以通过分层绘制要素的方式精准控制不同类别要素的样式,先绘制低数值和NA要素,再绘制目标数值区间的要素并应用调色板,具体实现如下:
方法1:深灰色填充(基础版)
library(ggnewscale) library(tidyverse) library(sf) library(RColorBrewer) nc <- sf::st_read(system.file("shape/nc.shp", package = "sf"), quiet = TRUE) nc$AREA[c(1,2,3)] <- NA ggplot() + # 绘制AREA≤0.1的要素,填充深灰色 geom_sf(data = nc %>% filter(AREA <= 0.1 & !is.na(AREA)), fill = "grey30", color = "white") + # 绘制NA值要素,填充浅灰色 geom_sf(data = nc %>% filter(is.na(AREA)), fill = "grey90", color = "white") + # 开启新的填充比例尺,避免和前面的固定颜色冲突 new_scale_fill() + # 绘制AREA>0.1的要素,应用Spectral调色板 geom_sf(data = nc %>% filter(AREA > 0.1), aes(fill = AREA), color = "white") + scale_fill_gradientn(colors = brewer.pal(9, "Spectral")) + labs(fill = "AREA (>0.1)") + theme_minimal()
方法2:填充图案(增强区分度)
如果需要用填充图案替代深灰色,提升视觉区分度,可以使用ggpattern包实现:
library(ggpattern) ggplot() + # AREA≤0.1的要素用斜线图案+深灰色填充 geom_sf_pattern(data = nc %>% filter(AREA <= 0.1 & !is.na(AREA)), fill = "grey30", pattern = "stripe", pattern_color = "white", pattern_fill = "white", pattern_density = 0.1, color = "white") + # NA值要素填充浅灰色 geom_sf(data = nc %>% filter(is.na(AREA)), fill = "grey90", color = "white") + new_scale_fill() + # AREA>0.1的要素应用Spectral调色板 geom_sf(data = nc %>% filter(AREA > 0.1), aes(fill = AREA), color = "white") + scale_fill_gradientn(colors = brewer.pal(9, "Spectral")) + labs(fill = "AREA (>0.1)") + theme_minimal()
原方法问题说明
- 第一种尝试:两个
geom_sf图层叠加时,后绘制的图层会覆盖前一个,且fill = AREA > 0.1是逻辑值,和后续数值型fill的比例尺冲突,导致样式混乱。 - 第二种尝试:使用
filter过滤了数据,导致AREA>0.1的要素未被绘制,无法展示完整地图。
内容的提问来源于stack exchange,提问作者rez
相关产品推荐
相关产品推荐

