我如何 select 基于其在 igraph 中的边之一的节点?

How do I select a node based on one of its edges in igraph?

如果我有如下代码:

library(igraph)

g <- erdos.renyi.game(20, 50 , type = "gnm" , directed = F , loops = F) %>%
  set_vertex_attr("a", value = 0) %>%
  set_vertex_attr("aa", value = 0) %>%
  set_edge_attr("b", value = 0) %>%
  set_vertex_attr("z", value = 0) 

V(g)$aa <- sample(c(0, .25, .5, .75, 1), vcount(g), replace = TRUE, prob = c(0.3, 0.15, 0.3, 0.15, 0.1))

V(g)$a[V(g)$aa <= V(g)$z & V(g)$a == 0] <- 1

V(g)$z <- sapply(V(g), function(x) { 
    NeighborList = neighbors(g, x) ; 
    ifelse(length(NeighborList) > 0, 
    length(NeighborList[NeighborList$a == 1])/length(NeighborList),0) } )

sum <- sum(head_of(g,E(g))$a==0 & tail_of(g,E(g))$a==0)

E(g)$b[head_of(g,E(g))$a==0 & tail_of(g,E(g))$a==0] <- sample(rep(0:1, c(sum-1, 1)), sum)

g <- delete_edges(g, E(g)[E(g)$b == 1])

其中删除了一条边,如何更改刚刚失去连接的节点的属性?因此,如果节点 1 和 5 丢失了它们之间的边,我如何在不指定 1 和 5 的情况下更改 a 的属性值(这样无论删除什么边都可以使用它)

一种方法是将列出连接节点的数据框放在一起,然后检查更新图中缺少哪个节点。我混合使用 igraph、基本 R 和 tidyverse 函数来完成此操作,但可能有更好的方法。下面的代码可以打包成一个函数,它接受一个 igraph 对象,删除一条边和 returns 更新的 igraph 对象以及边被删除的节点的名称。

首先,让我们重新创建您的图表,但我们将设置可重复性的种子:

set.seed(2)
g <- erdos.renyi.game(20, 50 , type = "gnm" , directed = F , loops = F) %>%
  set_vertex_attr("a", value = 0) %>%
  set_vertex_attr("aa", value = 0) %>%
  set_edge_attr("b", value = 0) %>%
  set_vertex_attr("z", value = 0) 

V(g)$aa <- sample(c(0, .25, .5, .75, 1), vcount(g), replace = TRUE, prob = c(0.3, 0.15, 0.3, 0.15, 0.1))

V(g)$a[V(g)$aa <= V(g)$z & V(g)$a == 0] <- 1

V(g)$z <- sapply(V(g), function(x) { 
  NeighborList = neighbors(g, x) ; 
  ifelse(length(NeighborList) > 0, 
         length(NeighborList[NeighborList$a == 1])/length(NeighborList),0) } )

sum <- sum(head_of(g,E(g))$a==0 & tail_of(g,E(g))$a==0)

E(g)$b[head_of(g,E(g))$a==0 & tail_of(g,E(g))$a==0] <- sample(rep(0:1, c(sum-1, 1)), sum)

现在检测删除了哪条边:

library(tidyverse)

创建一个数据框,列出 g 当前连接的节点:

adj = as.data.frame(get.edgelist(g)) %>% mutate(adj_before=1)

adj
   V1 V2 adj_before
1   1  3          1
2   1  4          1
3   4  5          1
...
13  5 10          1
14  9 10          1
15  1 11          1
...
48  7 20          1
49  9 20          1
50 10 20          1

现在我们将按照您指定的方式删除一条边。

g <- delete_edges(g, E(g)[E(g)$b == 1])

现在我们可以创建一个数据框,列出哪些节点在更新的图中 gleft_join 连接到现有的 adj 数据框。删除边的节点对行中会有一个NA

adj = adj %>% 
  left_join(as.data.frame(get.edgelist(g)) %>% 
              mutate(adj_after=1))

adj
   V1 V2 adj_before adj_after
1   1  3          1         1
2   1  4          1         1
3   4  5          1         1
...
13  5 10          1         1
14  9 10          1        NA
15  1 11          1         1
...
48  7 20          1         1
49  9 20          1         1
50 10 20          1         1

要获得一个列出边被删除的两个节点的向量,您只需要 select adj_after 所在的行 NA:

Vs = unlist(adj[which(is.na(adj$adj_after)), c("V1","V2")])

Vs
V1 V2 
 9 10

现在,假设您要为刚刚删除边的节点更改属性 a

# Current attribute `a` values:
V(g)$a
[1] 1 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 1 1 1
V(g)$a[Vs] = 3

V(g)$a
[1] 1 0 0 1 0 0 0 0 3 3 0 0 1 0 0 0 0 1 1 1