The equation for Network Modularity is given on its wikipedia page (and in reputable books). I want to see it working in some code. I have found this is possible using the modularity library for igraph used with R (The R Foundation for Statistical Computing).
I want to see the example below (or a similar one) used in the code to calculate the modularity. The library gives on example but it isn't really what I want.
Let us have a set of vertices V = {1, 2, 3, 4, 5} and edges E = {(1,5), (2,3), (2,4), (2,5) (3,5)} that form an undirected graph.
Divide these vertices into two communities: c1 = {2,3} and c2 = {1,4,5}. It is the modularity of these two communities that is to be computed.
library(igraph)
g <- graph(c(1,5,2,3,2,4,2,5,3,5))
membership <- c(1,2,2,1,1)
modularity(g, membership)
Some explanation here:
The vector I use when creating the graph is the edge list of the graph. (In igraph versions older than 0.6, we had to subtract 1 from the numbers because igraph uses zero-based vertex indices at that time, but not any more).
The i-th element of the membership vector membership gives the index of the community to which vertex i belongs.
Related
how can I create a complete list of dyads from a vertex list?
I have a list (1, 2, 3...) and I need to generate a list containing all possible dyads from that list (1-1, 1-2, 1-3, 2-1, 2-2,...).
I've tried with get.edgelist, but it doesn't work, because the graph is not fully connected (all nodes are connected among them).
Thanks
Using igraph, you can grab all edges of a graph using E(g). If you'd want all possible edges, you can apply it on a complete graph (a graph that is fully connected). If the vertices in your graph are indeed in sequence from 1 to n, you can use make_full_graph() to make a Kn - that is to say a fully connected graph. In this example, the graph has 14 vertices.
g <- make_full_graph(14, directed=F)
el <- as_edgelist(g)
edges <- E(g)
edges_list <- split(el, rep(1:nrow(el), each = ncol(el)))
edges_vert <- unlist(list(t(el)))
edges will be the igraph-object, but I think what you're after is a list in R, like edges_list.
As you see, length(edges_list) is 91 since it is an undirected graph, and the number of edges in complete graphs is a function of the number of vertices.
A complete graph with n vertices is commonly written Kn and has these many edges:
Note that in igraph dyads are called edges and nodes are called vertices.
I'm using igraph community-detection and the community sizes are either too small or too large. Is there any way to specify the size of the detected communities? If not, is there any way for me to manually split or merge communities detected from igraph? Thanks!
Whilst I don't think it's possible to set/specify the size of a community detected by igraph, some of the community detection algorithms allow you to specify how many communities you want (an alternative to splitting/merging).
You can use either the cluster_spinglass() function and set spins to be the number of communities desired. Or use one of the hierarchical methods and then use cut_at() to get the desired number of communities, using the no argument to specify how many communities you want.
Example code:
# Set up your graph object
g <-[an igraph object] # set up your graph
# Use spinglass to create a set number of communities
sg <- g %>% cluster_spinglass(spins = 10) # produces 10 communities using spinglass algorithm
# Use hierarchical methods and cut_at to create a set number of communities
walk <- g %>% cluster_walktrap() %>% cut_at(no = 10)
eb <- g %>% cluster_edge_betweenness() %>% cut_at(no = 10)
Note that the spinglass method will give you back a communities object, whereas the cut_at method simply gives you back the community indices for all nodes in the graph (i.e. a simple numeric vector).
You can find more details on the communities help page.
I'm fairly new to IGraph in R.
I'm doing community detection using IGraph and have already built my communities /clusters using the walktrap technique.
Next, within each cluster, I want to count the number of vertices between each two certain vertices. The reason I want to do this is, for each vertex XX, I want to list vertices that are connected to XX via say max 3 vertices, meaning no further than 3 vertices away from XX.
Can anyone help how this can be done in R please?
making a random graph (for demonstration):
g <- erdos.renyi.game(100, 1/25)
plot(g,vertex.size=3)
get walktrap communities and save as vertex attribute:
V(g)$community<-walktrap.community(g, modularity = TRUE, membership = TRUE)$membership
V(g)$community
now make a subgraph containing only edges and vertices of one community, e.g. community 2:
sub<-induced.subgraph(g,v=V(g)$community==2)
plot(sub)
make a matrix containing all shortest paths:
shortestPs<-shortest.paths(sub)
now count the number of shortest paths smaller or equal to 3.
I also exclude shortest paths from each node to itself (shortestPaths!=0).
also divide by two because every node pair appears twice in the matrix for undirected graphs.
Number_of_shortest_paths_smaller_3 <- length(which(shortestPs<=3 & shortestPs!=0))/2
Number_of_shortest_paths_smaller_3
Hope that's close to what you need, good luck!
I would like to reproduce the kind of "community summary" graph like on page 6 of this paper:
http://arxiv.org/pdf/0803.0476v2.pdf
First a community algorithm is employed on the graph, e.g.:
wc <- walktrap.community(subgraph)
mc <- multilevel.community(subgraph)
Then the vertices are grouped according to community. The size of the community node is a function of the membership size and the edge width is a function of the total edges going from any member of community A to community B.
Please note I don't just want to encode community as color or convex hulls like this:
V(inSubGraph)$color <- commObj$membership+1
plot.igraph( inSubGraph, vertex.color = V(inSubGraph)$color)
or with the convex hulls:
plot(commObj, inSubGraph)
Use the contract.vertices function with the membership vector that the community detection method provides, followed by simplify. In particular:
Assign a numeric vertex attribute with a value of 1 to each vertex as follows: V(g)$size = 1
Assign a numeric edge attribute with a value of 1 to each edge as follows: E(g)$count = 1
Contract the communities into vertices as follows: comm.graph <- contract.vertices(g, wc$membership, vertex.attr.comb=list(size="sum", "ignore")); basically this specifies that the size attribute of the vertices being contracted should be summed and every other vertex attribute should be ignored. (See ?attribute.combination in R for more details). This call contracts the vertices but leaves the original edges so you now have as many edges between the vertices as there were in the original graph between the communities.
Collapse the multiple edges as follows: comm.graph <- simplify(comm.graph, remove.loops=FALSE, edge.attr.comb=list(count="sum", "ignore")).
You now have a graph named comm.graph where the vertices represent the communities of the original graph, the size vertex attribute corresponds to the number of vertices in each community in the original graph, and the count edge attribute corresponds to the number of edges between communities in the original graph.
I need to draw a network with 5 nodes and 20 directed edges (an edge connecting each 2 nodes) using R, but I need two features to exist:
To be able to control the thickness of each edge.
The edges not to be overlapping (i.e.,the edge form A to B is not drawn over the edge from B to A)
I've spent hours looking for a solution, and tried many packages, but there's always a problem.
Can anybody suggest a solution please and provide a complete example as possible?
Many Thanks in advance.
If it is ok for the lines to be curved then I know two ways. First I create an edgelist:
Edges <- data.frame(
from = rep(1:5,each=5),
to = rep(1:5,times=5),
thickness = abs(rnorm(25)))
Edges <- subset(Edges,from!=to)
This contains the node of origin at the first column, node of destination at the second and weight at the third. You can use my pacake qgraph to plot a weighted graph using this. By default the edges are curved if there are multiple edges between two nodes:
library("qgraph")
qgraph(Edges,esize=5,gray=TRUE)
However this package is not really intended for this purpose and you can't change the edge colors (yet, working on it:) ). You can only make all edges black with a small trick:
qgraph(Edges,esize=5,gray=TRUE,minimum=0,cut=.Machine$double.xmin)
For more control you can use the igraph package. First we make the graph:
library("igraph")
g <- graph.edgelist(as.matrix(Edges[,-3]))
Note the conversion to matrix and subtracting one because the first node is 0. Next we define the layout:
l <- layout.fruchterman.reingold(g)
Now we can change some of the edge parameters with the E()function:
# Define edge widths:
E(g)$width <- Edges$thickness * 5
# Define arrow widths:
E(g)$arrow.width <- Edges$thickness * 5
# Make edges curved:
E(g)$curved <- 0.2
And finally plot the graph:
plot(g,layout=l)
While not an R answer specifically, I would recommend using Cytoscape to generate the network.
You can automate it using a RCytoscape.
http://bioconductor.org/packages/release/bioc/html/RCytoscape.html
The package informatively named 'network' can draw directed networks fairly well, and handle your issues.
ex.net <- rbind(c(0, 1, 1, 1), c(1, 0, 0, 1), c(0, 0, 0, 1), c(1, 0, 1, 0))
plot(network(ex.net), usecurve = T, edge.curve = 0.00001,
edge.lwd = c(4, rep(1, 7)))
The edge.curve argument, if set very low and combined with usecurve=T, separates the edges, although there might be a more direct way of doing this, and edge.lwd can take a vector as its argument for different sizes.
It's not always the prettiest result, I admit. But it's fairly easy to get decent looking network plots that can be customized in a number of different ways (see ?network.plot).
The 'non overlapping' constraint on edges is the big problem here. First, your network has to be 'planar' otherwise it's impossible in 2-dimensions (you cant connect three houses to gas, electric, phone company buildings without crossovers).
I think an algorithm for planar graph layout essentially solves the 4-colour problem. Have fun with that. Heuristics exist, search for planar graph layout, and force-directed, and read Planar Graph Layouts