如何在ggplot中用行政边界多边形替代散点图的数据点?
用行政边界多边形替代散点展示数据的实现方案
我想要创建一幅图表,用行政边界轮廓替代数据点来展示数据。目前已实现新西兰地区面积的有序散点图,但不清楚如何将nz_map中的行政多边形定位到绘图空间中对应点的位置,替代原有的散点。
原代码如下:
# 加载包 library(tidyverse) library(sf) library(rnaturalearth) # 获取新西兰行政边界地图 nz_map <- ne_states(country = "new zealand", returnclass = "sf") # 筛选南北岛地区并计算面积(单位:平方公里) nz_map <- nz_map %>% select(name, region) %>% filter(region %in% c("South Island", "North Island")) %>% mutate(area = as.vector(st_area(.)/1e6)) # 计算多边形中心点用于绘制散点 nz_map_pnts <- st_centroid(nz_map) # 绘制有序散点图 ggplot() + geom_point(data = nz_map_pnts, aes(reorder(name, area), y = area)) + labs(x = "地区", y = "面积(平方公里)") + theme_classic()+ theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust = 1))
原散点图效果:
解决方案步骤
核心思路是对每个行政多边形做归一化缩放+平移,将其转换为可定位到散点位置的“迷你地图”:
- 归一化每个多边形:把每个多边形的坐标转换到[0,1]的统一范围,消除原始地理坐标的差异;
- 缩放和平移定位:根据原散点的x(排序后的地区)和y(面积)坐标,将归一化后的多边形缩放并平移到对应位置;
- 绘制迷你地图:用
geom_sf绘制处理后的多边形,保留原坐标轴的信息。
修改后的完整代码
# 加载包 library(tidyverse) library(sf) library(rnaturalearth) # 获取并处理新西兰行政边界数据 nz_map <- ne_states(country = "new zealand", returnclass = "sf") %>% select(name, region) %>% filter(region %in% c("South Island", "North Island")) %>% mutate(area = as.vector(st_area(.)/1e6)) # 定义多边形归一化函数:将单个多边形坐标缩放到[0,1]范围 normalize_poly <- function(poly) { # 获取多边形的坐标范围 bbox <- st_bbox(poly) # 计算偏移量和缩放比例 x_offset <- bbox[["xmin"]] y_offset <- bbox[["ymin"]] x_scale <- bbox[["xmax"]] - x_offset y_scale <- bbox[["ymax"]] - y_offset # 对坐标做归一化转换 poly_normalized <- (poly - c(x_offset, y_offset)) / c(x_scale, y_scale) return(poly_normalized) } # 对每个地区的多边形做归一化处理 nz_map_normalized <- nz_map %>% group_by(name) %>% mutate(geometry = list(normalize_poly(geometry))) %>% ungroup() # 计算每个地区对应的散点位置(x为排序后的因子水平,y为面积) nz_map_pos <- nz_map %>% mutate(x_pos = as.integer(reorder(name, area)), # 转换为数值型x坐标 y_pos = area) # 将归一化后的多边形平移缩放至对应位置 # 缩放系数scale_factor控制迷你地图的大小,可根据需求调整 scale_factor <- 0.3 nz_map_plot <- nz_map_normalized %>% left_join(nz_map_pos, by = "name") %>% mutate(geometry = geometry * scale_factor + c(x_pos - scale_factor/2, y_pos - scale_factor/2)) # 绘制最终图表 ggplot() + # 绘制迷你行政边界 geom_sf(data = nz_map_plot, aes(fill = area), color = "black", size = 0.2) + # 添加y轴参考线(可选) geom_hline(data = nz_map_pos, aes(yintercept = y_pos), linetype = "dashed", color = "gray50") + # 设置坐标轴和标签 scale_x_continuous(breaks = nz_map_pos$x_pos, labels = nz_map_pos$name) + labs(x = "地区", y = "面积(平方公里)", fill = "面积") + theme_classic() + theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust = 1))
代码说明
- 归一化函数:确保每个地区的多边形都被缩放到相同的相对尺寸,避免因原始地理范围差异导致迷你地图大小悬殊;
- 缩放系数:
scale_factor可根据图表尺寸调整,避免迷你地图之间重叠; - 定位逻辑:将归一化后的多边形中心对齐到原散点的位置,
x_pos由排序后的地区名称转换为数值,保证顺序与原散点图一致; - 填充色:可选添加
fill = area,让迷你地图的颜色也反映面积大小,增强数据表达。
内容的提问来源于stack exchange,提问作者flee
相关产品推荐
相关产品推荐

