Load the packages that we will need for this exercise, and also set the random number seed
In [31]:
suppressPackageStartupMessages(library(igraph))
library(plyr)
Set the random number seed to 1337:
In [30]:
set.seed(1337)
Write a recursive function extend_seqs_by_one_recurser that will take an undirected igraph::Graph object and a list of vertex sequences (each vertex sequence of length k' <= max_k) and make a new, larger list of sequences (each of length k' + 1), each consisting of a one-vertex extension to the subgraph corresponding to the length k' sequence.
In [2]:
extend_seqs_by_one_recurser <- function(mygraph, myseqs, k) {
if (k > 1) {
unique(unlist(unlist(lapply(extend_seqs_by_one_recurser(mygraph, myseqs, k-1),
function(myseq) {
lapply(myseq, function(myvertex) {
lapply(setdiff(neighbors(mygraph, myvertex), myseq),
function(myneighbor) {
sort(c(myseq, myneighbor))
})
})
}),
recursive=FALSE),
recursive=FALSE))
} else {
myseqs
}
}
Write a function key_motifs that will take a directed igraph::Graph object mydigraph and a list myseqs of subgraphs described by vertex sequences, and computes in and out degree of each of the vertices in each of the subgraphs:
In [ ]:
key_motifs <- function(mydigraph, myseqs) {
lapply(myseqs, function(myseq) {
outdeg_myseq <- sort(sapply(myseq, function(myvert) {sum(mydigraph[myvert, setdiff(myseq, myvert)])}))
indeg_myseq <- sort(sapply(myseq, function(myvert) {sum(mydigraph[setdiff(myseq, myvert), myvert])}))
c(indeg_myseq, outdeg_myseq)
})
}
In [33]:
nvertices <- 6
medges_step <- 3
G = sample_pa(n=nvertices, m=medges_step)
summary(G)
Plot the graph that you created
In [14]:
plot(G)
Run the function extend_seqs_by_one_recurser on the undirected version of G, with k=3. Take a look at the results:
In [15]:
subgraphs <- extend_seqs_by_one_recurser(as.undirected(G), 1:nvertices, 3)
subgraphs
Call key_motifs on the directed graph G and the subgraph vertex sequences subgraphs, which will return a list of lists. Stack the lists into a matrix using do.call and rbind. Take a look at your matrix:
In [29]:
list_of_lists <- key_motifs(G, extend_seqs_by_one_recurser(as.undirected(G), 1:nvertices, 3))
subgraph_degree_counts <- do.call(rbind, list_of_lists)
subgraph_degree_counts
Make a data.frame out of the subgraph_degree_counts matrix and tabulate the number of times each unique row appears, using plyr::count:
In [35]:
plyr::count(data.frame(subgraph_degree_counts))
Compare to the counts from calling igraph::motifs on G, with the default k=3:
In [36]:
motifs(G)
Now let's do a four-vertex motifcount on the same graph, by nesting the various function calls that we used for the subgraph motif analysis with k=3 above:
In [37]:
plyr::count(data.frame(do.call(rbind, key_motifs(G, extend_seqs_by_one_recurser(as.undirected(G), 1:nvertices, 4)))))
Let's compare to what we get when we call igraph::motifs on G, using k=4 (omit all NA values and 0 counts, and display only the nonzero counts returned). You may find it helpful to use the function na.omit:
In [38]:
counts <- na.omit(motifs(G,4))
counts[counts > 0]
In [39]:
?motifs
Did the R code correctly calculate the subgraph motif counts?