在R中如何基于col1精准合并邻接矩阵/边列表与参考数据框?
针对shapefile邻接关系与降雨数据合并的问题解答
1. 手动添加ID合并的方法是否正确?
手动按行序添加ID再合并非常容易出错,除非你能绝对保证shapefile的要素顺序和参考数据框的行顺序完全一致(比如两者都是从同一个数据源导出、从未做过排序/筛选操作)。只要其中一方的顺序被改变(比如shapefile按空间范围排序,数据框按col1排序),ID和col1的对应关系就会完全混乱,这种方法不推荐。
2. 更精准的基于共同键的合并方式
核心思路是始终用唯一标识col1作为合并的键,而不是依赖行序生成的ID。具体步骤如下:
步骤1:提前建立ID与col1的映射表
不管用什么工具生成邻接矩阵/边列表,先把shapefile中每个要素的索引(即生成邻接关系时的ID)和col1绑定成映射表:
# 假设用sf包读取的shapefile对象是sf_obj id_col1_map <- data.frame( element_id = 1:nrow(sf_obj), col1 = sf_obj$col1 )
步骤2:将邻接矩阵/边列表的ID替换为col1
- 邻接矩阵:直接把矩阵的行名和列名替换成
col1的值,后续操作全程用col1标识:
# 假设邻接矩阵是adj_matrix(比如用spdep::nb2mat生成) rownames(adj_matrix) <- sf_obj$col1 colnames(adj_matrix) <- sf_obj$col1
- 边列表:生成边列表时直接用
col1替代ID,以spdep包为例:
library(spdep) # 生成邻接邻居列表 nb <- poly2nb(sf_obj) # 把邻居的ID转换为对应的col1值 nb_col1 <- lapply(nb, function(neighbor_ids) sf_obj$col1[neighbor_ids]) # 生成以col1为标识的边列表 edge_list <- data.frame( from = rep(sf_obj$col1, sapply(nb_col1, length)), to = unlist(nb_col1) )
步骤3:用col1合并降雨数据
直接用merge()或dplyr::left_join()以col1为键合并,完全避免ID对应错误:
# 假设参考降雨数据框是rain_df # 给边列表的from节点加降雨数据 edge_list_with_rain <- edge_list %>% dplyr::left_join(rain_df, by = c("from" = "col1")) %>% dplyr::rename(rainfall_from = rainfall) %>% # 给to节点加降雨数据 dplyr::left_join(rain_df, by = c("to" = "col1")) %>% dplyr::rename(rainfall_to = rainfall)
3. 借助shapefile/igraph直接添加col1避免歧义
完全可以,两种方式都能跳过ID映射的步骤:
基于sf(shapefile)对象直接生成带col1的邻接关系
用sf包处理时,全程绑定col1属性,生成的邻接关系直接用col1标识,不需要额外合并:
library(sf) library(spdep) sf_obj <- st_read("your_shapefile.shp") # 生成邻居列表时直接关联col1 nb <- poly2nb(sf_obj) nb_col1 <- lapply(nb, function(x) sf_obj$col1[x]) # 直接生成带col1的边列表 edge_list <- data.frame( from = rep(sf_obj$col1, lengths(nb_col1)), to = unlist(nb_col1) )
基于igraph对象直接添加col1和降雨属性
把邻接关系转成igraph时,直接将col1和降雨数据作为节点属性绑定,后续分析无需合并:
library(igraph) # 从邻接矩阵创建igraph对象 g <- graph_from_adjacency_matrix(adj_matrix, mode = "undirected") # 给节点添加col1属性 V(g)$col1 <- sf_obj$col1 # 给节点添加降雨属性(通过col1匹配) V(g)$rainfall <- rain_df$rainfall[match(V(g)$col1, rain_df$col1)] # 查看节点属性 head(data.frame(col1 = V(g)$col1, rainfall = V(g)$rainfall))
内容的提问来源于stack exchange,提问作者stats_noob
相关产品推荐
相关产品推荐

