R igraph is_matching always False - r

I am trying to apply the is_matching function in the igraph R package. I don't know why my answer is always FALSE, even when it is clearly a matching. Here is my code:
library(igraph)
relations=data.frame(from=c(1,2),to=c(3,4))
g <- graph_from_data_frame(relations, directed=FALSE, vertices=1:4)
mm=c(1,3)
is_matching(g,mm)
[1] FALSE
I really appreciate any help!

I have no idea why this works and your code doesn't because they are nearly identical, but:
relations <- data.frame(from=c(1, 3),to=c(2,4))
g1 <- graph_from_data_frame(relations, directed=FALSE, vertices=c(1, 2, 3, 4))
mm <- c(2,1,4,3)
is_matching(g1, mm)
[1] TRUE
The difference here is that the vertices incident to the matching edges in mm are given in reverse order, e.g. (1->2, 3->4) is (2,1,4,3). This is strange because, if I construct the edge directions as you have (1->3, 2->4):
relations <- data.frame(from=c(1, 2),to=c(3,4))
g1 <- graph_from_data_frame(relations, directed=FALSE, vertices=c(1, 2, 3, 4))
mm <- c(3,1,4,2)
is_matching(g1, mm)
[1] FALSE
It comes out as FALSE. I tried to deconstruct the function's code and couldn't make sense of it, mostly because it calls commands that don't seem to exist in igraph, such as as.igraph.vs. If anybody can shed light on this, that would be great.

Related

R igraph incidence matrix to graph object

I have one possibly very stupid question.
I have following matrix:
inc <- matrix(sample(0:1, 15, repl=TRUE), 5, 5)
colnames(inc) <- letters[1:5]
rownames(inc) <- letters[1:5]
Now when I use igraph to create an igraph object, the object understands rownames and colnames as two seperate nodes.
library(igraph)
incg <- graph_from_incidence_matrix(inc)
plot(incg)
The result is obviously kinda useless. Maybe I'm completely misunderstanding igraph, but how do I get it to understand that colnames and rownames are the same node?
So I would want a network object that shows the relation of a->b as a directed edge.
Thank you for your help!

Why does cluster_infomap in igraph R give different communities each time?

I am using the cluster_infomap function from igraph in R to detect communities in a undirected, unweighted, network with ~19,000 edges, but I get a different number of communities each time I run the function. This is the code I am using:
clusters <- list()
clusters[["im"]] <- cluster_infomap(graph)
membership_local_method <- membership(clusters[["im"]])
length(unique(membership_local_method))
The result of the last line of code ranges from 805-837 in the tests I have performed. I tried using set.seed() in case it was an issue of random number generation, but this does not solve the problem.
My questions are (1) why do I get different communities each time, and (2) is there a way to make it stable?
Thanks!
cluster_infomap (see ?igraph::cluster_infomap for help) finds a
community structure that minimizes the expected description length of
a random walker trajectory
Whenever you deal with random number generation, then you get different results on each run. Most of the time, you can override this by setting a seed using set.seed (see ?Random for help) beforehand:
identical(cluster_infomap(g), cluster_infomap(g))
# [1] FALSE
identical({set.seed(1);cluster_infomap(g)},{set.seed(1);cluster_infomap(g)})
# [1] TRUE
or graphically:
library(igraph)
set.seed(2)
g <- ba.game(150)
coords <- layout.auto(g)
par(mfrow=c(2,2))
# without seed: different results
for (x in 1:2) {
plot(
cluster_infomap(g),
as.undirected(g),
layout=coords,
vertex.label = NA,
vertex.size = 5
)
}
# with seed: equal results
for (x in 1:2) {
set.seed(1)
plot(
cluster_infomap(g),
as.undirected(g),
layout=coords,
vertex.label = NA,
vertex.size = 5
)
}

How can I count the second degree of all vertices in a network graph in R?

The number of first degree connections in a network (random graph) is easily counted with with the function:
g <- erdos.renyi.game(10, 1/10, directed = TRUE)
d1 <- degree(g, mode="out")
However, with which function can I count the second degree connections of each node?
I suggest using neigborhood as an alternative to the degree function. This allows you to specify any order of the neighborhood.
d1 <- sapply(neighborhood(g, 1, mode="out"), length)-1
d2 <- sapply(neighborhood(g, 2, mode="out"), length)-1
If you have graphs with loops, you should check if this still gives the desired result.
Edit: Thanks #Ryan for pointing out that neighborhood.size is actually the much better answer than neighborhood.
d1 <- neighborhood.size(g, 1, mode="out")-1
d2 <- neighborhood.size(g, 2, mode="out")-1
Edit: Thanks #Ryan for the neighborhood.size function! I used it and it works, however in order to optain the number of the second degree connections you need to subtract d1 from d2, then you only have the second degree connections:
d1 <- degree(g, mode="out")
d2 <- neighborhood.size(g, 2, mode="out")-d1-1

Generating small world network with fixed degree

I would like to generate a small world network with a fixed degree of 10.
I have tried watts.strogatz.game(1, 100, 5, 0) which results in a degree of 10 but only 5 neighbours for each node.
I'm guessing this is because the network is undirected. is there any way to make it undirected?
The igraph package contains many functions to create and manipulate graphs.
In particular, the get.edgelist function returns the list of edges, in the format you want.
The erdos.renyi.game function, when you set the probability to 1, generates complete graphs.
library(igraph)
g1 <- erdos.renyi.game(5, 1)
plot(g1)
get.edgelist(g1)
The degree.sequence.game function generates random graphs with a prescribed degree distribution.
g2 <- degree.sequence.game( c(3,3,3,2,1,1,1), method="vl" )
plot(g2)
The watts.strogatz.game function generates small-world networks.
g <- watts.strogatz.game(1, 100, 5, 0.05)
plot(g)

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