How do I merge two nodes into a single node using igraph - r

I am trying to merge two nodes (call them 'V' and 'U') in a graph (G) into a single node (V).
G is a hyperlink network of 779 nodes (websites). Each edge represents a hyperlink. V and U are actually the same website, but unfortunately the webpages from that website have become split into two separate nodes. So I want to put them back together into a single node.
I have researched the contract.vertices function, but I cannot understand how to adapt it here.
Here are the attributes of my graph (G).
> G
IGRAPH D--- 779 3544 --
+ attr: Image File (v/c), Ringset (v/n), Country Code TLD (v/n), Generic TLD (v/n), Number of Pages (v/n), Categorical 1 (v/n), Categorical 2 (v/n),
Categorical 3 (v/n), id (v/c), label (v/c), Width (e/n)
I have two nodes that I want to merge together:
> V(g)$id[8]
[1] "http://www.police.uk/"
and
> V(g)$id[14]
[1] "http://police.uk/"
In total there are 779 nodes and 3544 edges in the graph.
I want these two nodes to become a single node in the graph (i.e. they will have the same "id"). All inlinks and outlinks from/to other nodes will now point only to this new single node.
All other attributes will remain the same, with the exception of Number of Pages (the value of this will be the sum of both the nodes before they are merged).

contract.vertices is indeed the right function to try, but its API is a bit complicated since it is designed to be able to merge not only a single pair of nodes but also several pairs in a single pass. (It can also permute vertices). To this end, it requires a mapping from the old vertex IDs to the new ones.
In case you are unfamiliar with vertex IDs: igraph identifies each vertex of the graph with an integer in the range 1 to N where N is the number of vertices. The mapping that contract.vertices requires must be a list of length N where the i-th element of the list contains the new ID of the node corresponding to ID i before merging.
Suppose that your graph contains 10 nodes. The following mapping vector will simply map each node to the same ID that it already has, so it will not do any merging:
c(1,2,3,4,5,6,7,8,9,10)
Now, suppose that you want to merge node 7 into node 4. You have to tell igraph that the new ID of node 7 will be 4, so you have to change the 7th element in the above vector to 4:
c(1,2,3,4,5,6,4,8,9,10)
This will almost do the job; the problem is that igraph requires the node IDs to be in the range 1 to N and since you still have a node with ID 10 according to the above mapping, igraph will not delete the old node 7. You can either delete it manually with delete.vertices after you contracted the vertices, or you can specify a different mapping that not only merges node 7 into node 4 but also changes the ID of node 8 to 7, node 9 to 8 and node 10 to 9:
c(1,2,3,4,5,6,4,7,8,9)
Now, since you also want the Number of Pages attribute of the new node to be the sum of the values of the two old nodes, you must tell igraph what to do with the vertex attributes during the merge. The vertex.attr.comb parameter of contract.vertices serves this purpose. In your case, the value of vertex.attr.comb should be something like this:
list("Number of Pages"="sum", "first")
where "Number of Pages"="sum" means that the new value of the Number of Pages attribute should be calculated by summing the old attribute values, and "first" means that for all other attributes not mentioned here, the new value should be determined by the old value of the first node among the set of nodes that are merged into a single one. See ?attribute.combination in R for more details about the format of this argument.

Related

How to create network with both edges and isolates using statnet/igraph

My question is similar to the one posted here: Network adding edges error
I am creating a network from scratches: I have data about 228 vertices, over a period of 13 years. In the first year, I have just 1781 edges: they do not involve all of my vertices (barely 164), therefore the remaining nodes should result as isolated.
I created the network starting from my edgelist, using the code
fdi.graph.2003 <- graph_from_data_frame(fdi.edge.2003, directed = T, vertices = fdi.attr.2003)
where fdi.edge.2003 is a data.frame containing edge attributes (including some potential weight columns): it only involves 164 vertices out of the total vertices defined by fdi.attr.2003 is a data.frame containing a row for each vertex that is involved in the edgelist (164 in total).
all i get is a network with 164 vertices and no isolates. However, I know they do exist in my data! Any suggestion on how to do it? I think that I shoul initialize a network with all 228 vertices, adding their attributes and then adding the edges. However, nothing I am trying is working: rather, I am receiving the most disparate errors related to "Illegal vertex reference in addEdges_R".
Any suggestion is more than welcome, also in the case it would involve the alternative package igraph, for which I am finding the same problem
Filippo
Use add.isolates from the sna package
net1 = as.network(cbind(1:3, 3:5)) #5 vertices, 3 edges
net2 = as.network(add.isolates(net1, 10), matrix.type = "edgelist") #15 v, 3 e
And then you'll probably want to create new vertex names, e.g.
net2%v%"vertex.names" = 1:15

In iGraph in R, collapsing 2 nodes into 1 node [duplicate]

I am trying to merge two nodes (call them 'V' and 'U') in a graph (G) into a single node (V).
G is a hyperlink network of 779 nodes (websites). Each edge represents a hyperlink. V and U are actually the same website, but unfortunately the webpages from that website have become split into two separate nodes. So I want to put them back together into a single node.
I have researched the contract.vertices function, but I cannot understand how to adapt it here.
Here are the attributes of my graph (G).
> G
IGRAPH D--- 779 3544 --
+ attr: Image File (v/c), Ringset (v/n), Country Code TLD (v/n), Generic TLD (v/n), Number of Pages (v/n), Categorical 1 (v/n), Categorical 2 (v/n),
Categorical 3 (v/n), id (v/c), label (v/c), Width (e/n)
I have two nodes that I want to merge together:
> V(g)$id[8]
[1] "http://www.police.uk/"
and
> V(g)$id[14]
[1] "http://police.uk/"
In total there are 779 nodes and 3544 edges in the graph.
I want these two nodes to become a single node in the graph (i.e. they will have the same "id"). All inlinks and outlinks from/to other nodes will now point only to this new single node.
All other attributes will remain the same, with the exception of Number of Pages (the value of this will be the sum of both the nodes before they are merged).
contract.vertices is indeed the right function to try, but its API is a bit complicated since it is designed to be able to merge not only a single pair of nodes but also several pairs in a single pass. (It can also permute vertices). To this end, it requires a mapping from the old vertex IDs to the new ones.
In case you are unfamiliar with vertex IDs: igraph identifies each vertex of the graph with an integer in the range 1 to N where N is the number of vertices. The mapping that contract.vertices requires must be a list of length N where the i-th element of the list contains the new ID of the node corresponding to ID i before merging.
Suppose that your graph contains 10 nodes. The following mapping vector will simply map each node to the same ID that it already has, so it will not do any merging:
c(1,2,3,4,5,6,7,8,9,10)
Now, suppose that you want to merge node 7 into node 4. You have to tell igraph that the new ID of node 7 will be 4, so you have to change the 7th element in the above vector to 4:
c(1,2,3,4,5,6,4,8,9,10)
This will almost do the job; the problem is that igraph requires the node IDs to be in the range 1 to N and since you still have a node with ID 10 according to the above mapping, igraph will not delete the old node 7. You can either delete it manually with delete.vertices after you contracted the vertices, or you can specify a different mapping that not only merges node 7 into node 4 but also changes the ID of node 8 to 7, node 9 to 8 and node 10 to 9:
c(1,2,3,4,5,6,4,7,8,9)
Now, since you also want the Number of Pages attribute of the new node to be the sum of the values of the two old nodes, you must tell igraph what to do with the vertex attributes during the merge. The vertex.attr.comb parameter of contract.vertices serves this purpose. In your case, the value of vertex.attr.comb should be something like this:
list("Number of Pages"="sum", "first")
where "Number of Pages"="sum" means that the new value of the Number of Pages attribute should be calculated by summing the old attribute values, and "first" means that for all other attributes not mentioned here, the new value should be determined by the old value of the first node among the set of nodes that are merged into a single one. See ?attribute.combination in R for more details about the format of this argument.

Get node descendants in a tree graph

I have a directed graph (grafopri1fase1) the graph has no loops and it has a tree structure (not binary tree).
I have an array of nodes (meterdiretti) that i have extracted from the graph (grafopri1fase1) matching a condition.
I would like to know starting from each node of Meterdiretti how many nodes are under each node of Meterdiretti.
The result I would like to have is a Matrix with the following format
first column------------ second column
meterdiretti[1] -------- total amount of nodes reachable starting from meterdiretti[1]
meterdiretti[2] -------- total amount of nodes reachable starting from meterdiretti[2]
....
meterdiretti[n] ----------total amount of nodes reachable starting from meterdiretti[n]
Take a punt at what you want - it would be good if you could add a reproducible example to your question.
I think what you want is to count the descendents of a node. You can do this with neighborhood.size and mode="out" argument.
library(igraph)
# create a random graph
g <- graph.tree(17, children = 2)
plot(g, layout=layout.reingold.tilford)
# test on a single node
neighborhood.size( g, vcount(g), "1", "out") - 1
# [1] 16
# apply over a few nodes
neighborhood.size( g, vcount(g), c(1,4,7), "out") - 1
[1] 16 4 2

Search common subgraph between two graphs

I have two graphs G, H labeled and I want to extract all common subgraph of two graphs, I got to a part that is:
1 - extract all the nodes that are in common, but I'm stuck on the part that includes:
2 - Step 1: Take the First vertex and store it in a set P = {first element} (which will be the set of all common subgraph), and go to 2nd if it is adjacent to the first of the two P graph G and H, we add it, and so on, but I do not know how to do it when i have more than 2
That is a NP-complete problem. See http://en.wikipedia.org/wiki/Subgraph_isomorphism_problem

Partitioning adjacency matrix of bipartite graph

Lets say I have a graph G with its adjacency matrix A. I know that G is bipartite.
How can I split the vertices in G into the two sets that always form a bipartite graph?
Thanks!
Declare an array which of size equal to the number of vertices, setting each element to 0 initially. Then perform a depth-first search through the graph, recording the "level number" that you are on as you go. This starts at 1, and alternates between 1 and 2 with each edge traversed. For every vertex reached, assign the current level to the corresponding entry of which, and (if it was previously 0) recurse to process its children. Afterwards, all elements of which will be either 1 or 2, and which[i] indicates which set vertex i belongs to.
Intuitively, you can imagine that each traversal from parent to child in the DFS takes you "down" a level, and each traversal back takes you back "up". By the bipartite property, all vertices on even levels can be connected only to vertices on odd levels and vice versa, so labelling nodes "even" or "odd" suffices to partition them into the two sets.
If your graph contains more than one component, you will of course need a separate DFS for each component.

Resources