constructing complete subgraph in igraph - r

I'm pretty new to R. I wanna know that given a list of node ID's of a graph is there any fast way to connect all the edges between that vertices and create a clique in that graph?
p.s: I'm looking for a really fast method because I'm working on a very large graph.
Thanks in advance.

Given a vector of vertices idx, we may use combn to create a vector of edges to be added:
g1 <- erdos.renyi.game(20, 1 / 20)
idx <- 3:8
g2 <- g1 + edges(c(combn(idx, 2)))
maximal.cliques(g2)
# ...
# [[14]]
# + 6/20 vertices, from 137d7ad:
# [1] 6 3 8 7 5 4

Related

How to select a graph vertex with igraph in R?

In Python you can simply use graph.select() (atleast when reading the documentation: https://igraph.org/python/doc/api/igraph.VertexSeq.html) to select a vertex based on a value. I have a huge graph connecting movies that share an actor. However I would simply like to select one vertex from that graph and then plot it with its direct neighbors. I'm running into issues when I want to select just that single vertex.
I had hoped something like worked
graph.movies.select('Snatch (2000)')
But no luck.
Another approach I took was grabbing the single Snatch vertex by filtering all others out and then adding the edges.
snatch.graph <- induced.subgraph(g.movies, vids=V(g.movies)$name == 'Snatch (2000)')
snatch.edges <- edges(g.movies, "Snatch (2000)")
add_edges(snatch.graph, snatch.edges$edges)
However this returns an empty graph with only the snatch vertex.
My goal is to grab the Snatch vertex and plot this vertex, its DIRECT neighbors and the edges amomng them. Any suggestions? Thanks alot :D Been stuck o nthis for a quite a while -.-
You can use ?ego to grab the neighbours or ?make_ego_graph to form the graph. (Depending on whether your graph is directed or not, you may need to use the mode argument).
An example:
library(igraph)
# create some data
set.seed(71085002)
n = 10
g = random.graph.game(n, 0.25)
V(g)$name = seq_len(n)
# grab neighbours of node "1"
# set mindist = 0 to include node itself
# set order for the stepsize of the neigbourhood;
nb_g = make_ego_graph(g, order=1, node="1", mindist=0)[[1]]
# plot
# you could use the `layout` argument to
# keep nodes in the same position
op = par(mfrow=c(1,2), oma=rep(0,4))
plot(g, vertex.size=0, vertex.label.cex=3, main="Full graph")
plot(nb_g, vertex.size=0, vertex.label.cex=3, main="Sub graph")
par(op) # reset
If you just need a list of the neighbouring nodes:
ego(g, order=1, node="1", mindist=0)
# [[1]]
# + 4/10 vertices, named, from 00cfa70:
# [1] 1 4 6 9
I think the method using ego (by #user20650) is comprehensive and efficient.
Here is another option if you would like to find the sub-graph built on direct neighbors, which applies distances + induced_subgraph
> induced_subgraph(g, which(distances(g, "1") <= 1))
IGRAPH 99f872b UN-- 4 3 -- Erdos renyi (gnp) graph
+ attr: name (g/c), type (g/c), loops (g/l), p (g/n), name (v/n)
+ edges from 99f872b (vertex names):
[1] 1--4 1--6 1--9

Matching edges in 2 graphs

I have 2 graphs, lets call them g1 and g2. The graph g2 has the same structure as g1 but contains new edges that are not present in g1. I have to find these edges.
g1 <- graph(edges=c(1,2,2,3,1,3,3,4,2,4,1,5), n=5, directed=FALSE)
g2 <- graph(edges=c(1,2,2,3,1,3,3,4,2,4,1,5,3,5), n=5, directed=FALSE)
In this case what i'm looking for is the edge 3--5.
So far i thought of using the complementer of g1 then matching it with the edges from g2 to find these new edges. The problem is that i'm having trouble with the syntax. (new to R)
g1_complement <- complementer(g1)
Now i'd like to get only the new edges that are in g2 but NOT in g1. I was thinking of doing this.
E(g1_complement)[E(g1_complement) %in% E(g2)]
I was expecting to get only the new edges, but this returns all the g1_complement edges. I am only using igraph as library.
Please find below one possible solution using the difference() function from the igraph library.
Reprex
library(igraph)
g1 <- graph(edges=c(1,2,2,3,1,3,3,4,2,4,1,5), n=5, directed=FALSE)
g2 <- graph(edges=c(1,2,2,3,1,3,3,4,2,4,1,5,3,5), n=5, directed=FALSE)
difference(g2, g1)
#> IGRAPH 9fb5e8c U--- 5 1 --
#> + edge from 9fb5e8c:
#> [1] 3--5
Created on 2022-01-30 by the reprex package (v2.0.1)
We can try
> E(g2)[!E(g2) %in% E(g1)]
+ 1/7 edge from 9fdc2d2:
[1] 3--5
> E(g2)[setdiff(E(g2), E(g1))]
+ 1/7 edge from 9fdc2d2:
[1] 3--5

"sna" or "igraph" : Why do I get different degree values for undirected graph?

I am doing some basic network analysis using networks from the R package "networkdata". To this end, I use the package "igraph" as well as "sna". However, I realised that the results of descriptive network statistics vary depending on the package I use. Most variation is not too grave but the average degree of my undirected graph halved as soon as I switched from "sna" to "igraph".
library(networkdata)
n_1 <- covert_28
library(igraph)
library(sna)
n_1_adjmat <- as_adjacency_matrix(n_1)
n_1_adjmat2 <- as.matrix(n_1_adjmat)
mean(sna::degree(n_1_adjmat2, cmode = "freeman")) # [1] 23.33333
mean(igraph::degree(n_1, mode = "all")) # [1] 11.66667
This doesn't happen in case of my directed graph. Here, I get the same results regardless of using "sna" or "igraph".
Is there any explanation for this phenomenon? And if so, is there anything I can do in order to prevent this from happening?
Thank you in advance!
This is explained in the documentation for sna::degree.
indegree of a vertex, v, corresponds to the cardinality
of the vertex set N^+(v) = {i in V(G) : (i,v) in E(G)};
outdegree corresponds to the cardinality of the vertex
set N^-(v) = {i in V(G) : (v,i) in E(G)}; and total
(or “Freeman”) degree corresponds to |N^+(v)| + |N^-(v)|.
(Note that, for simple graphs,
indegree=outdegree=total degree/2.)
A simpler example than yours makes it clear.
library(igraph)
library(sna)
g = make_ring(3)
plot(g)
AM = as.matrix(as_adjacency_matrix(g))
sna::degree(AM)
[1] 4 4 4
igraph::degree(g)
[1] 2 2 2
Vertex 1 has links to both vertices 2 and 3. These count in the
in-degree and also count in the out-degree, so
Freeman = in + out = 2 + 2 = 4
The "Note" in the documentation states this.

How to randomly change ties in a bipartite network without creating ties within the same level

I have an undirected bipartite network where I want to randomly switch ties around while still maintaining the same degree distribution.
Working in igraph, I've used the rewire() and keeping_degseq() functions to randomly switch edges between nodes as shown in the code below. However, this results in edges being created between nodes that are in the same mode. For this sample network, nodes 1 through 10 are in one mode, and nodes 11-14 are in another mode.
library(igraph)
set.seed(1)
b <- sample_bipartite(10,4,type = "gnp", p = 0.5)
b2 <- rewire(b, keeping_degseq(niter = 100))
b2
The resulting edges are:
[1] 1--13 3--11 5--11 3-- 6 7--12 1--11 9--12 9--11 7--14 8--13 12--13 4-- 6 13--14 11--14 10--11 1--12 2--10 3--14 5--14 6--14 12--14
8--14 6-- 9 10--14
Edges such as 12--13, 3--6, and 13--14 are between nodes in the same mode, which is a property of the original network that I want to preserve in this simulation.
Is there a different function that better serves my purpose? Is there a way to tell the rewire() function not create edges between nodes in the same mode?
Instead of doing something with edges, we may permute the vertices:
set.seed(1)
b1 <- sample_bipartite(10,4,type = "gnp", p = 0.5)
table(degree(b1))
# 1 2 3 4 5 6
# 4 3 2 2 2 1
(b2 <- permute(b1, c(sample(1:10), sample(11:14))))
# IGRAPH cf35948 U--B 14 20 -- Bipartite Gnp random graph
# + attr: name (g/c), p (g/n), type (v/l)
# + edges from cf35948:
# [1] 5--14 4--14 9--14 3--14 5--11 8--11 4--11 7--11 10--11 5--13 8--13 6--13
# [13] 7--13 3--13 10--13 5--12 4--12 2--12 1--12 10--12
table(degree(b2))
# 1 2 3 4 5 6
# 4 3 2 2 2 1
This approach is also easily generalizable to, say, multiple communities. It all depends on the blocks of shuffled vertex indices in the second argument of permute. Instead of thinking about shuffling, an easy way to see why this works is to think that we only switch around the names of the vertices.

How to randomly select 2 vertices from a graph in R?

I'm new to R, and I'm trying to randomly select 2 vertices from a graph.
What I've done so far is:
First, set up a graph
edgePath <- "./project1/data/smalledges.csv"
edgesMatrix <- as.matrix(read.csv(edgePath, header = TRUE, colClasses = "character"))
graph <- graph.edgelist(edgesMatrix)
The smalledges.csv is a file look like this:
from to
4327231 2587908
Then I get all the vertices from the graph into a list:
vList <- as.list(get.data.frame(graph, what = c("vertices")))
After that, I try to use:
sample(vList, 2)
But what I've got is an error:
cannot take a sample larger than the population when 'replace = FALSE'
I guess it's because R thinks what I want is 2 random lists, so I tried this:
sample(vList, 2, replace = TRUE)
And then I've got 2 large lists... BUT THAT'S NOT WHAT I WANTED! So guys, how can I randomly select 2 vertices from my graph? Thanks!
Not clear from your question whether you want just the vertices, or a sub-graph containing those vertices. Here's an example of both.
library(igraph)
set.seed(1) # for reproducible example
g <- erdos.renyi.game(10, 0.3)
par(mfrow=c(1,3), mar=c(1,1,1,1))
set.seed(1) # for reproducible plot
plot(g)
# random sample of vertices
smpl <- sample(1:vcount(g),5)
V(g)[smpl] # 5 random vertices
# Vertex sequence:
# [1] 9 5 7 2 4
# change the color of only those vertices
V(g)[smpl]$color="lightgreen" # make them light green
set.seed(1) # for reproducible plot
plot(g)
# create a sub-graph with only those vertices, retaining edge structure
sub.g <- induced.subgraph(g,V(g)[smpl])
plot(sub.g)

Resources