R语言:编写基于图网络的好友节点选择与计算函数求助
问题解决:用igraph实现好友网络节点选择与移除函数
需求回顾
需要实现一个函数完成以下步骤:
- 随机选择一个初始节点
- 随机选择一个“半径”(指与初始节点的最大路径距离)
- 在初始节点的半径范围内,随机选择若干连通的节点(包含初始节点)
- 计算这些节点的饼干总数
- 若总数在50-100之间则结束,否则从步骤1重新开始
- 将选中的节点从原图中移除
完整代码实现
set.seed(123) library(igraph) # 构建好友关系图 names <- c("John", "Alex", "Jason", "Matt", "Tim", "Luke", "Shawn", "Henry", "Steven", "Scott", "Adam", "Jeff", "Connor", "Peter", "Andrew", "Dave", "Daniel", "Benjamin", "Joseph", "Martin") g <- make_empty_graph(20) num_edges <- 40 edge_list <- sample(names, size = num_edges * 2, replace = TRUE) edge_list <- matrix(edge_list, ncol = 2, byrow = TRUE) g <- graph_from_edgelist(edge_list, directed = FALSE) V(g)$name <- names # 饼干数据框 cookies = data.frame(names = names, cookies = as.integer(rnorm(length(names), 20,10))) # 定义核心函数 select_and_remove_nodes <- function(g, cookies) { repeat { # STEP 1: 随机选择初始节点 original_node <- sample(V(g), 1)$name # STEP 2: 随机选择半径(最大路径距离) # 计算初始节点到所有连通节点的距离 dists <- distances(g, original_node) # 只保留连通节点的距离(排除不连通的Inf值) valid_dists <- dists[!is.infinite(dists)] max_possible_radius <- max(valid_dists) # 随机选半径(0表示只选初始节点自己) radius <- sample(0:max_possible_radius, 1) # STEP 3: 获取半径范围内的所有连通节点 # ego函数返回距离初始节点≤radius的节点集合 radius_nodes <- ego(g, order = radius, nodes = original_node, mode = "all")[[1]] radius_node_names <- V(g)[radius_nodes]$name # 随机选择若干节点(至少包含初始节点) num_to_select <- sample(1:length(radius_node_names), 1) # 确保初始节点被选中,其余从半径范围内随机选 selected_nodes <- c(original_node, sample(setdiff(radius_node_names, original_node), num_to_select - 1)) # STEP 4: 计算饼干总数 total_cookies <- sum(cookies$cookies[cookies$names %in% selected_nodes]) # STEP 5: 判断是否符合条件 if (total_cookies >= 50 && total_cookies <= 100) { cat("选中节点:", paste(selected_nodes, collapse = ", "), "\n") cat("饼干总数:", total_cookies, "\n") break } } # STEP 6: 从图中移除选中节点 g <- delete_vertices(g, selected_nodes) return(g) } # 调用函数更新图 g_updated <- select_and_remove_nodes(g, cookies) # 可视化更新后的图 plot(g_updated, vertex.label.cex = 0.7, vertex.label.color = "black")
关键代码说明
- 修正半径逻辑:之前的代码混淆了节点度数与路径距离,这里用
distances()计算初始节点到所有连通节点的路径长度,以最大路径长度作为半径上限,匹配需求中的“半径”定义。 - 高效获取半径内节点:用
ego()函数直接提取距离初始节点≤指定半径的所有连通节点,避免手动筛选的误差。 - 保证节点选择有效性:强制选中初始节点,再从半径范围内的其他节点中随机补充,确保选中集合与初始节点连通。
- 循环重试机制:用
repeat循环实现步骤5的重试逻辑,直到找到符合饼干总数条件的节点集合。 - 节点移除操作:通过
delete_vertices()完成节点移除,返回更新后的图对象。
内容的提问来源于stack exchange,提问作者stats_noob
相关产品推荐
相关产品推荐

