Using igraph: community membership of components built by decompose.graph() - r

I would appreciate help with using decompose.graph, community detection functions from igraph and lapply.
I have an igraph object G with vertex attribute "label" and edge attribute "weight". I want to calculate community memberships using different functions from igraph, for simplicity let it be walktrap.community.
This graph is not connected, that is why I decided to decompose it
into connected components and run walktrap.community on each component, and afterwards add a community membership vertex attribute to the original graph G.
I am doing currently the following
comps <- decompose.graph(G,min.vertices=2)
communities <- lapply(comps,walktrap.community)
At this point I get stuck since I get the list object with the structure I cannot figure out. The documentation on decompose.graph tells only that it returns list object, and when I use lapply on the result I get completely confused. Moreover, the communities are numbered from 0 in each component, and I don't know how to supply weights parameter into walktrap.community function.
If it were not for the components, I would have done the following:
wt <- walktrap.community(G, modularity=TRUE, weights=E(G)$weight)
wmemb <- community.to.membership(G, wt$merges,steps=which.max(wt$modularity)-1)
V(G)$"walktrap" <- wmemb$membership
Could anyone please help me solve this issue? Or provide some
information/links which could help?

You could use a loop:
library(igraph)
set.seed(2)
G <- erdos.renyi.game(100, 1/50)
comps <- decompose.graph(G,min.vertices=2)
length(comps) # 2 components, in this example
for(i in seq_along(comps)) { # For each subgraph comps[[i]]
wt <- walktrap.community(comps[[i]], modularity=TRUE, weights=E(comps[[i]])$weight)
wmemb <- community.to.membership(comps[[i]], wt$merges,steps=which.max(wt$modularity)-1)
V(comps[[i]])$"walktrap" <- wmemb$membership
}
It is possible to do it with lapply and mapply, but it is less readable.
comps <- decompose.graph(G,min.vertices=2)
wt <- lapply( comps, function(u)
walktrap.community(u, modularity=TRUE, weights=E(u)$weight)
)
wmemb <- mapply(
function(u,v) community.to.membership(u, v$merges,steps=which.max(v$modularity)-1),
comps, wt,
SIMPLIFY=FALSE
)
comps <- mapply(
function(u,v) { V(u)$"walktrap" <- v$membership; u },
comps, wmemb,
SIMPLIFY=FALSE
)

Related

How to use the convex_hull() function in the loop?

In my previous question I have used the convex_hull() function. We have a graph, where all nodes have zero degree and (x,y) coordinats. We need to create graph as sequence of convex hulls. We can stop the loop if only just one node has zero degree.
My attempt is:
library(igraph)
######################################################################
set.seed(5)
n=15
g <- graph.empty(n)
xy <- cbind(runif(n), runif(n))
in_points <- V(g)[degree(g)==0]
repeat {
cp <- convex_hull(xy[in_points, ])$resverts+1
g <- as.undirected(add_edges(g, c(t(embed(cp, 2)), cp[1], cp[length(cp)])))
in_points <- V(g)[degree(g)==0]
if (length(in_points)=1) {break}
}
plot(g, vertex.size=10, layout=xy)
One can see in the repeate loop the node 3 used twice.
Expected result is:
Question. How are correctly use output of convex_hull() function for sequential adding edges in the loop?
You can iteratively use chull and add_edges. You just need to make sure that input to add_edges is of correct format and track which nodes are not already part of outer convex hull.
xy <- cbind(seq_len(n), xy)
while(nrow(xy) > 1){
current_hull <- chull(xy[,2], xy[,3])
current_hull <- c(current_hull, current_hull[[1]])
g <- add_edges(g, as.vector(t(embed(xy[,1][current_hull], 2)[,2:1])))
xy <- xy[-current_hull,,drop = FALSE]
}

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!

R: Convert correlation matrix to edge list

I want to create a network graph of my data, where the weight of the edges is defined by the correlation coefficient in a correlation matrix. The connection is defined by being statistically significant or not.
Since I want to play around with some parameters I need to have this information in an edge list rather than in matrix form, but I'm struggling as to how to convert this. I have tried to used igraph as shown below, but I cannot figure out how to get the information on which correlations are significant and which are not into the edge list. I guess weight could be set to zero to code that info, but how do I combine a correlation matrix and a p-value matrix?
library(igraph)
g <- graph.adjacency(a,weighted=TRUE)
df <- get.data.frame(g)
df
It'd be great if you could provide a minimal reproducable example, but I think I understand what you're asking for. You'll need to make a graph from a matrix using graph_from_adjacency_matrix, but make sure to input something in the weighted parameter, because otherwise the elements in the matrix represent number of edges (less than 1 means no edges). Then you can create an edge list from the graph using as_data_frame. Then perform whatever calculation you want, or join any external data you have, then you can convert it back to a graph by using graph_from_data_frame
cor_mat <- cor(mtcars)
cor_g <- graph_from_adjacency_matrix(cor_mat, mode='undirected', weighted = 'correlation')
cor_edge_list <- as_data_frame(cor_g, 'edges')
only_sig <- cor_edge_list[abs(cor_edge_list$correlation) > .75, ]
new_g <- graph_from_data_frame(only_sig, F)
For the ones who still need this, here is the answer
library(igraph)
g <- graph.adjacency(a, mode="upper", weighted=TRUE, diag=FALSE)
e <- get.edgelist(g)
df <- as.data.frame(cbind(e,E(g)$weight))

Edit or Exclude Small igraph Modules During Plotting in R

Is it possible to exclude or edit the modules being plotted so that modules with only one node do not have a module boundary? In case below, hide the module boundary around 9 and 13.
set.seed(3)
g <- barabasi.game(20, m=2, directed=FALSE)
eb <- cluster_edge_betweenness(g)
plot(eb, g, layout=layout_with_fr)
You can get at this using the mark.groups argument to plot.communities. First create the default grouping, but then eliminate the groups with only one member.
MG = lapply(unique(eb$membership), function(m) { which(eb$membership == m) })
MG[sapply(MG, length) == 1] = NULL
plot(eb, g, mark.groups=MG, layout=layout_with_fr)

Create Condition for Connectors of Datapoints R

This is my Initial Data
library(igraph)
From <- c(1,2,3,4,5,6,7,8)
To <- c("NULL",1,2,3,2,"NULL",6,7)
Value<-c(4,2,2,7,1,2,7,2)
Data <- data.frame(From,To,Value)
Network <- graph.data.frame(Data[,c("From","To")],directed=TRUE)
Network<- Network - "NULL"
plot(Network)
I want to create a condition which adds a characterization of the Datapoints.
So far i was capable of creating, the first and 2nd Degree of Condition, but i'm not capable of finding an Solution on how to create the 3rd condition to finalize the whole Construct.
I was capable of creating the Condition for the Root and the Starter, my Problem is how could i construct the condition for the connectors of the Starters. In this case the Connectors should be number 2 and 3. And Finally who didn't got characterized should be called Follower.
Root: Writes to no NULL
Starter: Value>X
Connector: Connects the starters(There will always be only one way of connecting them)
Follower= Rest
Some code here
cond<-Data$To=="NULL"
ToP<-ifelse(cond,"Root","Follower")
cond<-Data$Value>3
ToP<- ifelse(cond,"Starter",ToP)
NewData<-cbind(Data,ToP)
View(NewData)
My FinalData should kinda look like this:
From <- c(1,2,3,4,5,6,7,8)
To <- c("NULL",1,2,3,2,"NULL",6,7)
Value<-c(4,2,2,7,1,2,7,2)
ToP<-c(Starter,Connector,Connector,Starter,Follower,Root,Starter,Follower)
Data <- data.frame(From,To,Value, ToP)
It's still a bit messier than I would like, bit this appears to assing the correct lables to the vertices
V(Network)$ToP <- ifelse(Data$To=="NULL","Root","Follower")
V(Network)$ToP[Data$Value>3] <- "Starter"
vs <- V(Network)[ToP=="Starter"]
sp <- shortest.paths(Network, vs,vs)
cx <- which(is.finite(sp) & lower.tri(sp), arr.ind=T)
for(i in nrow(cx)) {
pp <- get.shortest.paths(Network, c(vs)[cx[i,1]], c(vs)[cx[i,2]])
fidx <- tail(head(pp$vpath[[1]], -1), -1)
if(length(fidx)>0) {
V(Network)[fidx]$ToP<-"Connector"
}
}
#verify with plot
V(Network)$color <- as.numeric(factor(V(Network)$ToP))+1
plot(Network)
legend(.5, -.5, levels(factor(V(Network)$ToP)), col=2:5, pch=20)

Resources