Remove maximal cliques in igraph - r

I have a disconnected undirected network.
I want to identify and remove all the components that are cliques.
I do not want to remove all the cliques, just those that are themselves a component of the network.
How should I proceed?
library(igraph)
g <- graph_from_literal(a-b-c-d-b,e-f-g-e,h-i-l)
result <- graph_from_literal(a-b-c-d-b,h-i-l)

One solution is the following, but I do not know to what extent this is efficient in large networks.
d <- graph_from_literal(a-b-c-d-b,e-f-g-e,h-i-l)
d0 <- decompose.graph(d)
d1 <- disjoint_union(d0[unlist(lapply(d0, function(x) count_max_cliques(x)!=1))])

Related

R network package - is there a faster way to add edges?

I have an adjacency matrix (m) of 7000 nodes. Creating a network from this using
n <- 7000
m <- matrix(rbinom(3*n, 1, 0.2), n,n)
diag(m) <- 0
g <- network(m, directed = F)
is very slow. Is there a more efficient way of creating large random networks in R? Alternative methods such as using iGraph would also be appreciated.
With igraph, you can do:
library('igraph')
g <- graph.adjacency(m, mode='undirected')
The edges can then be retrieved using E(g) and vertices using V(g).
Check out the igraph docs for more information.

R iGraph: degree in the case of bidirectional edges

I have noticed that the function degree in iGraph doesn't straighforwardly allow to calculate the degree of the undirected skeleton graph of a directed graph, whenever bidirectional edges are involved.
For example,
g <-graph_from_literal( a-+b,a++c,d-+a,a-+e,a-+f )
d1 <- degree(g,v='a',mode="all")
# 6
nn <- unique(neighbors(g,'a',mode='all'))
d2 <- length(nn)
# 5
As I wanted d2, instead of d1, I have used a different route based on finding the neighbors of the considered vertex.
My question is: is there a better/faster way to do this, maybe using some other iGraph function that I'm not aware of?
Create an undirected copy of the graph, collapse the multiple edges in the undirected graph into a single edge, and then calculate the degree on that:
> g2 <- as.undirected(g, mode="collapse")
> degree(g2)

extract a connected subgraph from a subset of vertices with igraph

I have a graph G(V,E) unweighted, undirected and connected graph with 12744 nodes and 166262 edges. I have a set of nodes (sub_set) that is a subset of V. I am interested in extracting the smallest connected subgraph where sub_set is a part of this new graph. I have managed to get a subgraph where my subset of nodes is included but I would like to know if there is a way to minimise the graph.
Here is my code (adapted from http://sidderb.wordpress.com/2013/07/16/irefr-ppi-data-access-from-r/)
library('igraph')
g <- erdos.renyi.game(10000, 0.003) #graph for illustrating my propose
sub_set <- sample(V(g), 80)
order <- 1
edges <- get.edges(g, 1:(ecount(g)))
neighbours.vid <- unique(unlist(neighborhood(g, order, which(V(g) %in% sub_set))))
rel.vid <- edges[intersect(which(edges[,1] %in% neighbours.vid), which(edges[,2] %in% neighbours.vid)),]
rel <- as.data.frame(cbind(V(g)[rel.vid[,1]], V(g)[rel.vid[,2]]), stringsAsFactors=FALSE)
names(rel) <- c("from", "to")
subgraph <- graph.data.frame(rel, directed=F)
subgraph <- simplify(subgraph)
I have read this post
minimum connected subgraph containing a given set of nodes, so I guess that my problem could be "The Steiner Tree problem", is there any way to try to find a suboptimal solution using igraph?
Not sure if that's what you meant but
subgraph<-minimum.spanning.tree(subgraph)
produces a graph with the minimum number of edges in which all nodes stay connected in one component.

Calculate degree, closeness and betweenness in R

I have a data table which consists of names of users who post in the same thread in a forum, it looks like that:
X1 X2
1. g79 kian
2. g79 greyracer
3. g79 oldskoo1 ...
I need to calculate degree, closeness and betweenness. I'm using the following code:
library(igraph)
setwd("/Volumes/NATASHKA/api/R files")
load("edgelist_one_mode.rda")
load("map.rda")
load ("result.rda")
el <- as.matrix(whatwewant)
el[,1] <- as.character(el[,1])
el[,2] <- as.character(el[,2])
g <- graph.data.frame(el, directed=FALSE)
plot(g, edge.arrow.size=.5)
indegreeG <- degree(g, mode="in")
outdegreeG <- degree(g, mode="out")
totaldegreeG <- degree(g)
inclosenessG <- closeness(g, mode='in')
outclosenessG <- closeness(g, mode='out')
totalclosenessG <- closeness(g)
betweennessG <- betweenness(g)
forumG <- data.frame(V(g)$name, indegreeG, outdegreeG, totaldegreeG, inclosenessG, outclosenessG, totalclosenessG, betweennessG)
write.table(forumG,file="forumG.csv",sep=";")
The question is why do I get the same values for in-degree, out-degree and total-degree, the same for closeness? Besides, at the beginning I have 41213 users, but after analysis (when I calculate degree, etc..) I only have 37874. How could I lose so many observations? Please tell me if I have a mistake in the code.
Thanks
The reason you get the same value for in-degree, out-degree and total degree is because you are creating an undirected network with the graph.data.frame(el, directed=FALSE).
In an undirected network, the number of links from a node and to a node are the same and they are both equal to the global degree.
If you want a directed network, you will need to do graph.data.frame(el, directed=TRUE).
It will create a directed network in which the id in the first column of your dataframe is the id of the node sending the tie and the id in the second column indicates the node receiving that tie.
As for loosing nodes, my guess would be that you have some individuals who never interact with anyone and therefore are lost when you transform your two-mode network into one-mode (I assume you do this but don't show us how you do it because of your line:load("edgelist_one_mode.rda"))
Short of a reproducible example, I think that is all I can deduce from your code.

2nd Degree Connections in igraph

I think have this working correctly, but I am looking to mimic something similar to Facebook's Friend suggestion. Simply, I am looking to find 2nd degree connections (friends of your friends that you do not have a connection with). I do want to keep this as a directed graph and identify the 2nd degree outward connections (the people your friends connect to).
I believe my dummy code is achieving this, but since the reference is on indices and not vertex labels, I was hoping you could help me modify the code to return useable names.
### create some fake data
library(igraph)
from <- sample(LETTERS, 50, replace=T)
to <- sample(LETTERS, 50, replace=T)
rel <- data.frame(from, to)
head(rel)
### lets plot the data
g <- graph.data.frame(rel)
summary(g)
plot(g, vertex.label=LETTERS, edge.arrow.size=.1)
## find the 2nd degree connections
d1 <- unlist(neighborhood(g, 1, nodes="F", mode="out"))
d2 <- unlist(neighborhood(g, 2, nodes="F", mode="out"))
d1;d2;
setdiff(d2,d1)
Returns
> setdiff(d2,d1)
[1] 13
Any help you can provide will be great. Obviously I am looking to stay within R.
You can index back into the graph vertices like:
> V(g)[setdiff(d2,d1)]
Vertex sequence:
[1] "B" "W" "G"
Also check out ?V for ways to get at this type of info through direct indexing.
You can use the adjacency matrix $G$ of the graph $g$ (no latex here?). One of the properties of the adjacency matrix is that its nth power gives you the number of $n$-walks (paths of length n).
G <- get.adjacency(g)
G2 <- G %*% G # G2 contains 2-walks
diag(G2) <- 0 # take out loops
G2[G2!=0] <- 1 # normalize G2, not interested in multiplicity of walks
g2 <- graph.adjacency(G2)
An edge in graph g2 represents a "friend-of-a-friend" bond.

Resources