如何在igraph社区检测结果数据框中添加对应网络名称
解决方案:添加网络名称并优化代码
首先解决添加网络名称的核心需求,同时优化代码结构,提升效率和可读性:
步骤1:给网络列表命名
原代码的网络列表没有关联名称,首先给列表元素命名,方便后续提取对应网络的标识:
# 给网络列表命名,后续可直接提取网络名称 list_of_networks <- list(karate = karate, erdos_renyi_50 = g2)
步骤2:优化代码(替代嵌套for循环)
原代码存在重复计算(同一算法调用两次do.call),且嵌套循环可读性差。改用tidyverse工具链实现批量处理,逻辑更清晰,效率更高:
完整优化代码
library(igraph) library(igraphdata) library(tidyverse) # 加载并创建网络,同时为列表元素命名 data(karate) g2 <- erdos.renyi.game(50, .2) list_of_networks <- list(karate = karate, erdos_renyi_50 = g2) # 筛选需要的社区检测算法 clusters <- grep("^cluster_", ls("package:igraph"), value = TRUE)[-1] clusters <- clusters[!grepl("spinglass|fluid|leiden|walktrap|infomap|prop|optimal", clusters)] # 生成所有网络-算法组合,批量计算指标 results <- crossing( network_name = names(list_of_networks), algorithm = clusters ) %>% mutate( # 一次计算社区检测结果,避免重复调用 community = map2(network_name, algorithm, ~ do.call(.y, list(list_of_networks[[.x]]))), # 提取模块化度(数值型) modularity = map_dbl(community, modularity), # 提取社区数量(整数型) num_communities = map_int(community, length) ) %>% # 移除中间临时列(不需要可保留) select(-community) # 查看最终结果 print(results)
关键改进点
- 添加网络名称:通过给
list_of_networks命名,结合crossing自动生成network_name列,直接关联每个结果对应的网络 - 避免重复计算:原代码对同一网络+算法调用两次
do.call,现在仅计算一次社区结果,再从中提取指标,大幅提升效率 - 类型安全:用
map_dbl和map_int确保输出指标为数值/整数类型,避免原代码中字符转数值的潜在问题 - 可读性更强:管道式操作替代嵌套循环,逻辑一目了然,适合处理大量网络的场景
原代码的最小修改版本(保留for循环)
如果不想完全重构,仅需给原代码添加网络名称,可修改如下:
# 给网络列表命名 list_of_networks <- list(karate = karate, erdos_renyi_50 = g2) x <- 1:length(list_of_networks) container <- vector("list", length(x)) for (cluster in clusters) { for (i in x) { # 仅计算一次社区结果 comm <- do.call(cluster, list(list_of_networks[[i]])) result <- t(c( modularity(comm), length(comm), cluster, names(list_of_networks)[i] # 添加网络名称 )) container[[i]] <- rbind(result, container[[i]]) } } container %>% map(~ as_tibble(.)) %>% bind_rows() %>% rename( modularity = 1, num_communities = 2, algorithm = 3, network_name = 4 # 重命名网络名称列 )
内容的提问来源于stack exchange,提问作者avgoustisw
相关产品推荐
相关产品推荐

