如何用ggplot2复现R中区域空间依赖的k近邻网络图
Hey there! 我来帮你搞定用ggplot2复现这个空间近邻可视化的问题~核心就是从cS(listw对象)里提取出区域间的连接关系,再搭配区域中心点坐标来生成连线数据。下面是完整的分步解决方案:
步骤1:准备数据与空间权重对象
先把你的基础代码流程走一遍,顺便把sp对象转成sf格式——ggplot对sf的支持更友好,不用手动处理long/lat/group这些参数:
library(ggplot2) library(sf) library(spdep) # 读取数据并转成sf对象 URL <- "https://biogeo.ucdavis.edu/data/gadm3.6/Rsp/gadm36_CZE_1_sp.rds" data_sp <- readRDS(url(URL)) data_sf <- st_as_sf(data_sp) # 计算3近邻并生成对称的空间权重对象 cns <- knearneigh(coordinates(data_sp), k = 3, longlat = TRUE) scnsn <- knn2nb(cns, sym = TRUE) cS <- nb2listw(scnsn)
步骤2:提取连线所需的坐标数据
cS$neighbours是一个列表,每个元素对应一个区域的邻居索引。我们需要把这个列表展开成“区域-邻居”的配对,再和每个区域的中心点坐标结合,得到每条连线的起点和终点:
# 提取每个区域的中心点坐标,添加id列对应区域索引 centroids <- as.data.frame(coordinates(data_sp)) colnames(centroids) <- c("x", "y") centroids$id <- 1:nrow(centroids) # 把邻居列表展开为长格式的配对数据 nb_pairs <- stack(cS$neighbours) colnames(nb_pairs) <- c("neighbor_id", "id") nb_pairs$id <- as.numeric(as.character(nb_pairs$id)) # 把因子类型的id转为数值 # 合并起点(当前区域)和终点(邻居区域)的坐标 segments_data <- merge(nb_pairs, centroids, by = "id", suffixes = c("", "_start")) segments_data <- merge(segments_data, centroids, by.x = "neighbor_id", by.y = "id", suffixes = c("_start", "_end")) # 可选:去除重复连线(因为sym=T会生成双向连接,比如i→j和j→i) segments_data <- segments_data[segments_data$id < segments_data$neighbor_id, ]
步骤3:用ggplot2绘制可视化
现在有了区域多边形数据和连线数据,直接用geom_sf画区域,geom_segment画近邻连线即可:
ggplot() + # 绘制区域边界 geom_sf(data = data_sf, fill = NA, color = "black", linewidth = 0.8) + # 绘制近邻连线 geom_segment(data = segments_data, aes(x = x_start, y = y_start, xend = x_end, yend = y_end), color = "#ff4d4d", linewidth = 0.5) + # 优化主题,让图更简洁 theme_minimal() + theme(panel.grid = element_blank()) + labs(title = "Czech Republic Regions: 3-Nearest Neighbors Connections")
这样就能得到和基础plot()功能一致,但用ggplot2渲染的可视化图啦~
内容的提问来源于stack exchange,提问作者Petr
相关产品推荐
相关产品推荐

