如何在R的igraph中实现bipartite网络投影并将节点属性转为边权重
解决Bipartite图转单模图时保留属性作为边权重的问题
我明白你的核心需求:把人-项目/地点的双模图转换为人-人的单模加权图,其中边权重是两人共同参与的项目/地点的属性(预算、时长)之和,且同一个项目/地点的属性仅计算一次。
默认的bipartite_projection()函数只会统计两人共同连接的节点数量(比如共同参与的项目数),不会自动聚合属性值,所以我们需要手动处理属性的求和逻辑。下面结合你的示例数据给出完整解决方案:
步骤1:预处理数据(确保项目属性唯一)
首先要确保每个项目的预算是唯一的(避免重复计算同一个项目的预算)。如果原始数据里同一个项目有重复的预算值,先做去重处理:
# 你的原始数据 person_id <- c("X","Y","Z","Q","W","E","R","X","Y") project <- c("a","b","c","a","a","b","c","b","a") budget <- c(100,200,300,100,100,200,300,200,100) employ.data <- data.frame(person_id, project, budget) # 去重:每个项目只保留唯一的预算值 project_budgets <- unique(employ.data[, c("project", "budget")])
步骤2:高效生成加权单模图(推荐方法)
如果数据量较大,直接从数据框生成人员对的权重会更高效,逻辑也更清晰:
library(igraph) # 1. 按项目分组,获取每个项目对应的参与人员列表 project_people <- split(employ.data_clean$person_id, employ.data_clean$project) # 2. 遍历每个项目,生成所有参与人员的无序对,并绑定项目预算 weighted_edge_list <- lapply(names(project_people), function(proj_name) { people_in_proj <- project_people[[proj_name]] if(length(people_in_proj) < 2) return(NULL) # 少于2人的项目不生成边 # 生成该项目下的所有人员对 person_pairs <- combn(people_in_proj, 2, simplify = FALSE) # 转换为数据框,每条边对应项目预算 data.frame( from = sapply(person_pairs, `[`, 1), to = sapply(person_pairs, `[`, 2), weight = project_budgets$budget[project_budgets$project == proj_name], stringsAsFactors = FALSE ) }) # 3. 合并所有边数据,并按人员对求和权重 final_edges <- do.call(rbind, weighted_edge_list) %>% aggregate(weight ~ from + to, data = ., sum) # 4. 直接构建人员加权单模图 person_weighted_graph <- graph_from_data_frame(final_edges, directed = FALSE)
验证结果
比如查看X和Y的边权重:他们共同参与项目a(预算100)和项目b(预算200),权重应为100+200=300,执行E(person_weighted_graph)[X--Y]$weight即可验证结果正确。
适配你的第一个示例(人员-地点-时长)
如果是你最初的Person-EventLocation-DurationEvent数据,逻辑完全一致:
- 去重每个EventLocation对应的DurationEvent
- 按EventLocation分组生成参与人员列表
- 生成人员对并求和共同地点的时长,得到边权重
这样生成的加权单模图,可直接用于后续的加权中心性计算(比如betweenness()、closeness()时指定weights参数即可)。
内容的提问来源于stack exchange,提问作者Mr.Morgan
相关产品推荐
相关产品推荐

