R语言中使用apply或循环批量生成多学校多波次邻接矩阵列表
批量生成邻接矩阵的实现方案
生成的结果结构与你手动编写的代码输出完全一致:顶层为按学校命名的列表,每个学校元素下是按观测波次命名的邻接矩阵子列表,无需重复编写逐组处理代码。
方法1:base R 显式循环(无额外依赖,兼容性最好)
直接复用你现有的过滤-建图-转矩阵逻辑,通过两层循环遍历所有学校、波次,无需调整原有处理步骤:
# 加载依赖包 library(igraph) library(dplyr) # 初始化结果存储列表 school_list <- list() # 提取数据中所有唯一的学校ID all_schools <- unique(edges$school) # 外层循环:遍历每所学校 for (current_school in all_schools) { # 为当前学校初始化子列表,存储3个波次的邻接矩阵 current_wave_list <- list() # 内层循环:遍历所有观测波次 for (current_wave in unique(edges$wave)) { # 完全复用你原本的单组处理逻辑 adj_matrix <- edges %>% filter(school == current_school & wave == current_wave) %>% graph_from_data_frame(directed = TRUE) %>% as_adjacency_matrix() %>% as.matrix() # 按波次命名存入子列表 current_wave_list[[paste0("w", current_wave)]] <- adj_matrix } # 按学校ID命名存入顶层结果列表 school_list[[paste0("school", current_school)]] <- current_wave_list }
运行完成后,你原本手动生成的school1对象,直接通过school_list$school1即可调用,内容和手动编写的结果完全等价。
方法2:base R 嵌套lapply(避免显式循环,代码更简洁)
如果不想维护循环状态变量,可以用两层嵌套的lapply实现,逻辑和显式循环完全一致:
# 封装单组处理逻辑为独立函数 get_single_adj <- function(school_id, wave_id) { edges %>% filter(school == school_id & wave == wave_id) %>% graph_from_data_frame(directed = TRUE) %>% as_adjacency_matrix() %>% as.matrix() } # 生成最终结果列表 school_list <- lapply(unique(edges$school), function(s) { # 内层:对当前学校的所有波次生成矩阵列表 wave_res <- lapply(unique(edges$wave), function(w) get_single_adj(s, w)) # 为波次子列表设置名称 names(wave_res) <- paste0("w", unique(edges$wave)) wave_res }) # 为顶层列表的每个元素设置学校命名 names(school_list) <- paste0("school", unique(edges$school))
方法3:tidyverse/purrr 实现(和现有管道逻辑无缝衔接)
如果你日常使用tidyverse生态,用purrr系列函数可以大幅压缩代码量,和你原本的管道写法适配度最高:
library(purrr) library(dplyr) school_list <- edges %>% # 按学校、波次完成分组 group_by(school, wave) %>% # 对每个分组单独执行邻接矩阵转换 summarise(adj = list( graph_from_data_frame(cur_data(), directed = TRUE) %>% as_adjacency_matrix() %>% as.matrix() ), .groups = "drop") %>% # 按学校拆分数据块 split(.$school) %>% # 每个学校块单独提取对应波次的矩阵,生成命名子列表 map(~ set_names(.$adj, paste0("w", .$wave))) # 为顶层列表元素补充学校名前缀 names(school_list) <- paste0("school", names(school_list))
常见踩坑提示:如果某所学校某一波次存在孤立节点(即没有出现在任何边中的在册学生),直接基于边列表建图会导致邻接矩阵缺失这些节点的行/列。遇到这类情况时,可提前整理每个学校的全量在册学生列表,传入
graph_from_data_frame()的vertices参数补全节点即可,不需要修改循环或批量处理的整体逻辑。
内容的提问来源于stack exchange,提问作者L. Tucker
相关产品推荐
相关产品推荐

