如何让ggplot2的facet_grid仅按目标数据集ID分面并保留公共多边形叠加
解决ggplot2分面时公共多边形被拆分的问题
你遇到的核心问题是:ggplot的分面会默认对所有图层应用分面变量的过滤,导致美国轮廓(usa)被按id拆分到各个州的分面中。要让公共多边形在每个分面完整显示,有两种简单的解决思路:
方法一:让公共多边形图层不继承分面变量(推荐)
通过inherit.aes = FALSE告诉ggplot,这个图层不需要继承主数据的分面映射和变量,从而完整显示在所有分面中。同时推荐使用sf对象(ggplot对sf的支持更友好,无需手动指定x/y/group):
library(sf) library(ggplot2) library(maps) # 转换为sf格式(比Spatial对象更易用) usa <- st_as_sf(map(database="usa", fill=T, plot = FALSE)) usa_states <- st_as_sf(map(database="state", fill=T, plot = FALSE)) usa_states_subset <- usa_states[1:5, ] ggplot(data = usa_states_subset) + # 美国轮廓图层:设置inherit.aes=FALSE,不继承分面变量 geom_sf(data = usa, color = "red", fill = NA, size = 1, inherit.aes = FALSE) + # 州图层:正常按id分面 geom_sf(fill = "green", color = "black", alpha = 0.2, size = 0.3) + facet_grid(facets = id ~ .)
如果你坚持使用Spatial对象,修改后的代码如下:
library(sf) library(ggplot2) library(maps) usa <- as(st_as_sf(map(database="usa",fill=T, plot =FALSE)),"Spatial") usa_states <- as(st_as_sf(map(database="state",fill=T, plot =FALSE)),"Spatial") usa_states <- usa_states[c(1:5),] ggplot(data=usa_states)+ # 关键:inherit.aes=FALSE 避免继承主数据的id分面,同时用group=group确保usa的多边形正确绘制 geom_polygon(data=usa, aes(x = long, y = lat, group=group), size = 1, colour = "red", fill=NA, inherit.aes = FALSE)+ geom_polygon(aes(x = long, y = lat, group=id), size = 0.3, fill = "green", color="black", alpha=0.2)+ facet_grid(facets= id ~.)
方法二:复制公共多边形数据匹配每个分面
另一种思路是给美国轮廓数据添加每个州的id,让每个分面都能拿到完整的美国轮廓数据:
library(sf) library(ggplot2) library(maps) library(dplyr) usa <- st_as_sf(map(database="usa", fill=T, plot =FALSE)) usa_states_subset <- st_as_sf(map(database="state", fill=T, plot =FALSE))[1:5, ] # 复制usa数据,每个州id对应一份完整的美国轮廓 usa_faceted <- usa %>% crossing(id = usa_states_subset$id) ggplot(data = usa_states_subset) + geom_sf(data = usa_faceted, color = "red", fill = NA, size = 1) + geom_sf(fill = "green", color = "black", alpha = 0.2, size = 0.3) + facet_grid(facets = id ~ .)
问题根源解释
在你原来的代码中,ggplot(data=usa_states)将州数据设为主数据,facet_grid(id ~ .)指定按id分面。此时geom_polygon(data=usa, ...)会默认继承主数据的id变量,ggplot会尝试将usa的数据按当前分面的id过滤——但美国轮廓的id和州的id不匹配,要么导致分面中只显示usa的部分多边形,要么完全不显示,最终出现你看到的“轮廓被拆分”的现象。
内容的提问来源于stack exchange,提问作者Johannes
相关产品推荐
相关产品推荐

