J.Q
J.Q

Reputation: 1033

igraph: keeping only edges that containing vertices with different values of a vertex attribute

net is an igraph object:

IGRAPH f6d0c20 UN-- 60 150 -- 
+ attr: name (v/c), group (v/c), group1_flag (v/n), teams (v/c), ppl (v/c), ids
| (v/c), value (e/n)
+ edges from f6d0c20 (vertex names):
 [1] 132--115 132--113 132--131 132--141 132--133 173--174 173--122 173--175 173--172
[10] 173--152 173--161 173--121 173--171 173--293 173--292 105--103 105--112 105--102
[19] 105--113 105--101 105--121 105--104 105--322 105--321 105--343 103--102 103--162
[28] 103--101 103--111 103--171 103--104 103--322 103--263 103--261 114--112 114--115
[37] 114--174 114--113 114--175 114--111 114--171 114--203 114--225 114--345 112--115
[46] 112--164 112--113 112--175 112--111 112--171 142--115 142--153 142--171 142--141
[55] 115--174 115--122 115--113 115--151 115--101 115--111 115--171 115--293 115--304
+ ... omitted several edges

Vertices have a binary dichotomous attribute called group1_flag. Conveniently, the vertex ids store this info: any 3-digit ID beginning with a 1 will have a group1_flag = 1; others have group1_flag = 0. For example, the first edge (132--115) should be completely excluded from the graph, but the last edge printed above (115--304) should be included.

I have tried to produce this result with subset_edges():

crossgroupnet <- subgraph.edges(net, which(V(net)$group>"1"), delete.vertices = T)

but

  1. I'm not confident that I should be specifying vertex information in the function (but there isn't a cross-group edge attribute), and
  2. the result includes many in-group ties (it shouldn't) and omits many cross-group ties (e.g., 115--304):

plot(crossgroupnet, vertex.color = rainbow(2)[factor(V(crossgroupnet)$group1_flag)], vertex.label = V(crossgroupnet)$ids)

enter image description here

What am I missing?

Upvotes: 0

Views: 1408

Answers (1)

G5W
G5W

Reputation: 37661

At least as you described the problem, your code does not make sense. You generate the subgraph using:

crossgroupnet <- subgraph.edges(net, which(V(net)$group>"1"), delete.vertices = T)

The second argument to subgraph.edges should be a list of the edges that you wish to include, but which(V(net)$group>"1") will generate a sequence numbers based on vertices.

You do not really provide your network (the list of edges is truncated), but I will use your truncated list as my example (data below the answer). Here is the resulting graph.

plot(net, vertex.color=V(net)$group_flag+1)

Full graph

OK, now we need to select those edges whose ends are in different groups. We can use ends on the edges to get the relevant vertices and then check if they are in the same group. Keeping the edges with vertices in different groups, we can generate the subgraph that you seek.

CrossEdges = which(sapply(E(net), function(x) {
    length(unique(V(net)[ends(net, x)]$group_flag)) != 1 }))
SUB = subgraph.edges(net, CrossEdges)

plot(SUB, vertex.color=V(SUB)$group_flag+1)

Subgraph

Data

EL = read.table(text= "V1 V2
132 115 
132 113 
132 131 
132 141 
132 133 
173 174 
173 122 
173 175 
173 172
173 152 
173 161 
173 121 
173 171 
173 293 
173 292 
105 103 
105 112 
105 102
105 113 
105 101 
105 121 
105 104 
105 322 
105 321 
105 343 
103 102 
103 162
103 101 
103 111 
103 171 
103 104 
103 322 
103 263 
103 261 
114 112 
114 115
114 174 
114 113 
114 175 
114 111 
114 171 
114 203 
114 225 
114 345 
112 115
112 164 
112 113 
112 175 
112 111 
112 171 
142 115 
142 153 
142 171 
142 141
115 174 
115 122 
115 113 
115 151 
115 101 
115 111 
115 171 
115 293 
115 304", 
header=T)
EL$V1 =  as.character(EL$V1)
EL$V2 =  as.character(EL$V2)
EL = as.matrix(EL)

net = graph_from_edgelist(EL, directed = F)
V(net)$group_flag = as.numeric(floor(as.numeric(V(net)$name)/100) == 1)

Upvotes: 1

Related Questions