首页 > 解决方案 > 如何转换二分网络并使用一级节点属性作为 igraph (R) 中二级节点的边权重

问题描述

我现在正在尝试将二分二模图转换为其单模表示。问题是我想将节点属性从双模图保存到单模表示。例如,数据框由以下给出:

Person EventLocation DurationEvent Peter Bar 90 Jack Bar 90 Franz Train 20 Franz Bar 90 Laurie Train 20 Jack Train 20 ...

现在我想在 Person 和 EventLocation 列上使用 igraph 函数 bipartite_projection() 来获取人员网络,但我看不到如何预先保护可能转移到 Person 之间的边权重的附加节点属性(持续时间),例如带有权重的 Peter-Jack 90 或 Franz-Laurie 体重 20。

编辑:为了更精确,我添加了最后一行。边缘“Jack-Franz”现在对应于 90+20 = 110。但基本上我的问题只是与如何实现 bipartite_projection 相关,它将二分 igraph 网络的节点属性传输到单模式中的相应边缘属性igraph 网络。

编辑 2:我刚刚添加了另一个示例。首先,我在人员之间创建一个网络,然后我想将预算信息添加到人员边缘,这意味着两者吸引了多少项目预算(仅来自不同独特项目的预算总和作为权重)。然后我想做一些进一步的加权中心性计算:

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)
View(employ.data)
sna.complete.list <- employ.data
sna.list.complete.igraph.calc <- graph.data.frame(sna.complete.list)
V(sna.list.complete.igraph.calc)$type <- V(sna.list.complete.igraph.calc)$name%in%sna.complete.list$person_id
sna.list.complete.igraph.calc.one <- try(bipartite.projection(sna.list.complete.igraph.calc, type=V(sna.list.complete.igraph.calc)$type))
sna.statistics.persons <- sna.list.complete.igraph.calc.one[[2]]
plot.igraph(sna.statistics.persons)

EDIT3:我尝试重新表达我的担忧:

总体目标:得到一个加权图(节点之间的边值用一些值加权)

大纲/数据:

  1. 参与预算规模不同的不同项目的人员数据

  2. 将二分连接图(People-Project)转换为单模-People-People-graph

  3. 使用预算大小作为人与人之间边缘的权重。

但是对于两个人来说,这个价值应该只占参与独特项目的总和。因此,如果 A 和 B 仅通过预算大小为 100 的项目 x 连接,则边权重应为 100。如果他们还参与了另一个值为 20 的项目,则结果应为 120,以此类推。

我尝试在使用 bipartite.projection 期间传输此信息,但之后失败或无法实施此信息。

标签: rigraphbipartite

解决方案


bipartite_projection()只能收集的结构权重,也就是说,Peter 和 Jack 都隶属于 Train 和 Bar。处理边缘属性比较棘手。

如果您只想保留node属性,正如您在上面写的bipartite_projection()那样,绝对已经为您做到了。只需重新投影并找到保留的属性,如下所示:

V(unipartite_graph)$your_attributee

但是,如果您需要在重新投影时保留edge属性,那么之前有几个问题要问。

  • 当 Franz-Train-Jack 也有 Franz-Bar_Jack 时,应该如何处理多条路径?
  • 方向性在计算中起什么作用

几年前我需要完全相同的东西,并通过编写我自己的扩展重投影函数来解决它。这可能不是解决此问题的最短方法,而是通过二部图中每个单部顶点对之间的最短路径计算给定边缘属性的总和,返回保留(并汇总)一个边缘属性的图。

具有汇总边缘属性的重投影

请注意,该函数不计算单分 Laurie-Peter。您可以根据自己的喜好操作该功能。

这会重现您的示例数据并应用我的功能

# Reproduce your data
df <- data.frame(Person = c("Peter","Jack","Franz","Franz","Laurie","Jack"),
                 EventLocation = c("Bar","Bar","Train","Bar","Train","Train"),
                 DurationEvent = c(90,90,20,90,20,20), stringsAsFactors = F)


## Make bipartite graph from example data
g <- graph_from_data_frame(df, directed=FALSE)
# Set vertex type using bipartite.mapping() (OBS type should be boolean for bipartite_projection())
V(g)$type <- bipartite.mapping(g)$type


## Plot Bipartite graph
E(g)$label <- E(g)$DurationEvent
V(g)$color <- ifelse(V(g)$type, "red", "yellow")
V(g)$size <- ifelse(V(g)$type, 40, 20)
plot(g, edge.label.color="gray", vertex.label.color="black")

# Function to reproject a bipartite graph to unipartite projection while
# calculating an attribute-value sum between reprojected vertecies.
unipartite_projection_attr <- function(graph_bi, attribute, projection=FALSE){

  ## Make initial unipartite projection
  graph_uni <- bipartite_projection(graph_bi, which=FALSE)

  ## List paths in bipartite-graph along which to summarise selected attribute
  el <- as_edgelist(graph_uni)
  el <- matrix(sapply(el, function(x) as.numeric(which(x == V(graph_bi)$name))), ncol=2)

  ## Function to summarise given atribute-value
  summarise_graph_attribute_along_path <- function(source, target, attribute){
    attr_value <- edge_attr(g, attribute)
    path <- get.shortest.paths(g, source, target, output="epath")$epath[[1]]
    sum(E(g)$DurationEvent[path])
  }

  attr_uni <- mapply(summarise_graph_attribute_along_path, el[,1], el[,2], attribute)
  graph_uni <- set_edge_attr(graph_uni, attribute, value=attr_uni)

  (graph_uni)
}

# Use function to make unipartite projection
gg <- unipartite_projection_attr(g, "DurationEvent", FALSE)

# Visualise
V(gg)$color <- "yellow"
E(gg)$label <- E(gg)$DurationEvent
plot(gg, edge.label.color="gray", vertex.label.color="black")

祝你好运


推荐阅读