R igraph incidence matrix to graph object - r

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!

Related

How to use a different input to draw community polygons in igraph for R?

Could you please help me?
I love plotting networks with igraph for R. One nice feature is drawing polygons around the communities detected by a given algorithm.
When you use one of the community detection algorithms built in igraph, that's pretty straightforward. Like in this example with a random bipartite graph:
library(igraph)
graph <- sample_bipartite(10, 10, p = 0.5)
graph
graph.lou = cluster_louvain(graph)
graph.lou$membership
length(graph.lou$membership)
plot(graph.lou, graph)
But how can I use another kind of input to draw those polygons?
For instance, I usually calculate modularity using the package bipartite for R, because it has other algorithms that are better suited for two-mode networks.
So I'm trying to use the output from bipartite as an input for drawing community polygons in igraph. As in the following example:
library(bipartite)
matrix <- as_incidence_matrix(graph)
matrix
matrix.bec = computeModules(matrix, method = "Beckett")
modules <- module2constraints(matrix.bec)
modules
length(modules)
plot(modules, graph)
From the output of the computeModules function I'm able to extract a vector with community memberships using the module2constraints function. When I try to use it as a plotting input, I get this error message:
Error in xy.coords(x, y, xlabel, ylabel, log) :
'x' and 'y' lengths differ
Is it possible to use this output from bipartite in igraph, so polygons are automatically drawn around the communities?
I've looked into the documentation, searched here on StackOverflow, experimented some tricks, but found no solution.
Thank you very much!
I've found a solution, with help given in another question!
Actually, another way to draw polygons around communities in igraph for R is by using the argument mark.groups of the function plot.
However, this argument accepts only lists of community membership. So, if you want to use an output of the package bipartite in the format of a vector together with an igraph object, you need to convert it to a list first.
The info contained in the vector modules described in the original question needs to be complemented with vertex names and first become a data frame, then a list:
number <- seq(1:10)
row <- "row"
rowlabels <- paste(row, number, sep = "")
column <- "col"
columnlabels <- paste(column, number, sep = "")
matrix <- matrix(data = rbinom(100,size=1,prob=0.5), nrow = 10, ncol = 10,
dimnames = list(rowlabels, columnlabels))
library(bipartite)
matrix.bec <- computeModules(matrix, method = "Beckett")
modules <- module2constraints(matrix.bec)
df <- data.frame(c(rownames(matrix), colnames(matrix)), modules)
colnames(df) <- c("vertices", "modules")
list <- split(df$vertices, df$modules)
Now the object list can be used as a drawing input together with an igraph object:
library(igraph)
graph <- graph_from_incidence_matrix(matrix, directed = F)
plot(graph,
mark.groups = list)
That's one way to make bipartite and igraph talk to one another!
Thank you very much!

Remove maximal cliques in igraph

I have a disconnected undirected network.
I want to identify and remove all the components that are cliques.
I do not want to remove all the cliques, just those that are themselves a component of the network.
How should I proceed?
library(igraph)
g <- graph_from_literal(a-b-c-d-b,e-f-g-e,h-i-l)
result <- graph_from_literal(a-b-c-d-b,h-i-l)
One solution is the following, but I do not know to what extent this is efficient in large networks.
d <- graph_from_literal(a-b-c-d-b,e-f-g-e,h-i-l)
d0 <- decompose.graph(d)
d1 <- disjoint_union(d0[unlist(lapply(d0, function(x) count_max_cliques(x)!=1))])

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))

cluster igraph on attribute

I am fairly new to igraph in R and to clustering/partitioning algorithms in general.
I have a general question on clusters. My idea is to build a contiguous cluster from a (directed) graph based on an attribute. What I try to achieve is something very similar to https://www.sixhat.net/finding-communities-in-networks-with-r-and-igraph.html. However, I am not sure I understand the functions (e.g. cluster_walktrap()) correctly. (I know there are some clustering methods that work on directed graphs, and some that don't.)
As an example: I use the network net from http://kateto.net/networks-r-igraph. Assuming I would like to end up with contiguous clusters based on the attribute audience.size (contrary to a clustering based on the betweeness), how would I use a clustering function from igraph?
cluster_walktrap(net, weights = E(net)$audience.size, steps = 4)?
How do I interpret the weight in this case?
MWE with data from: http://www.kateto.net/wordpress/wp-content/uploads/2016/01/netscix2016.zip
library(igraph)
nodes <- read.csv("Dataset1-Media-Example-NODES.csv", header=T, as.is=T)
links <- read.csv("Dataset1-Media-Example-EDGES.csv", header=T, as.is=T)
net <- graph_from_data_frame(d=links, vertices=nodes, directed=T)
net <- simplify(net, remove.multiple = F, remove.loops = T)
cluster_walktrap(net, weights = E(net)$audience.size, steps = 4)
Thank you very much!

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