Create bipartite graph in R? - r

So this question has been asked here and here... but I cant seem to adapt it to my problem. I am trying to create a bipartite graph using the igraph package in R, that looks something like this:
The code im using to try this is:
# create all pairs and turn into vector for graph edges
pairs <- expand.grid(1:6, 1:6) # create all pairs
pairs <- pairs[!pairs$Var1 == pairs$Var2, ] # remove matching rows
ed <- as.vector(t(pairs)) # turn into vecotr
# create graph
g <- make_empty_graph(n = 6)
g <- add_edges(graph = g, edges = ed)
plot(g)
This will a create a graph... but im trying to make it resemble the graph in the image, with, say, (1,2,3) on the top and (4,5,6) on the bottom.
I tried using make_bipartite_graph() and layout_as_bipartite... but I cant seem to get it to work... any suggestions?

If the graph is created straight from the data.frame it will not be a bipartite graph.
library(igraph)
g <- graph_from_data_frame(df)
is.bipartite(g)
#[1] FALSE
But it will be a bipartite graph if created from the incidence matrix.
tdf <- table(df)
g <- graph.incidence(tdf, weighted = TRUE)
is.bipartite(g)
#[1] TRUE
Now plot it.
colrs <- c("green", "cyan")[V(g)$type + 1L]
plot(g, vertex.color = colrs, layout = layout_as_bipartite)

Related

Subset igraph plot in using activate function in R

I am trying to subset an igraph plot to display certain nodes based on a given vertex attribute. I have to subset them in the plot output to preserve the layout for the vertices. My code is the following:
plot.igraph(graph, layout=lo, vertex.label=NA, rescale=T, vertex.size = 4) %>%
tidygraph::activate(nodes) %>%
filter(period == 1)
But I receive the following error:
Error in UseMethod("activate") :
no applicable method for 'activate' applied to an object of class "NULL"
How can I subset the graph based on the vertex attribute "V(graph)$period", maintaining the vertices' layout?
Observe that class(plot(graph)) returns NULL.
Update, calculate subset as follows.
## Random example.
set.seed(20)
g <- make_ring(20)
V(g)$period <- sample(2, vcount(g), replace=TRUE)
V(g)$name <- V(g)
## Calculate subset of vertices
## and plot subgraph.
vvv <- V(g)[which(V(g)$period==1)]
g2 <- subgraph(g, vvv)
plot(g2)

recluster.cons function and colorful dendrogram

I created a dendrogram using the 'recluster.cons' function of the recluster package. I would like to know how to color the branches of the dendrogram by group resulting from this function.
tree <- recluster.cons(sp2, p=1)$cons # sp2 is a presence-absence matrix
plot(tree, direction="downwards")
Here is the current dendrogram:
You need to define how many clusters you want to get from the clustering (like cutree), and then using dendextend seems like an easier option. First I simulate a dataset that might look like yours:
library(recluster)
set.seed(222)
testdata = lapply(1:3,function(i){
truep = runif(200)
replicate(7,rbinom(200,size=1,prob=truep))
})
testdata = t(do.call(cbind,testdata))
rownames(testdata) = paste0(rep(letters[1:3],each=7),rep(1:7,3))
We plot it, 3 clusters of sites because it was simulated as such:
tree <- recluster.cons(sp2, p=1)$cons # sp2 is a presence-absence matrix
plot(tree,direction="downwards")
Then colour it:
dendextend
dend <- color_branches(as.dendrogram(tree),k=3)
plot(dend)

How to plot overlap clustering with a list of vertices of each group and the edge list by R?

I have a file csv including edge list of graph. After implementing CONGA
(Clustering Overlap Girven-NewMan alorithm), result is a list of vertices of each group.
I don't know how to plot it so that each group has different color in graph by R.
I can plot graph with edge list in R, but I don't know how to mark vertices in each group.
Input: edge list file and list of vertices in each group.
Output: graph with different color for each group.
output nearly like this
My English isn't good. Thanks for your support.
You plot colors using $color of vertices. Try to assign a color like V(g)$color <- 'green'.
It is better if you give us some code.
You say you get a list of your group-members. Convert the list to a vector, and sign a new color to each unique group-member value. I wrote this example code. I think it shows what you're after.
library(igraph)
get_a_random_network <- function() {
# EN: Function to get some random data to use as an example
g <- erdos.renyi.game(100, 60, type="gnm", directed=F, loops=FALSE)
g <- g %>% delete_vertices( V(g)[degree(g)==0] )
(g)
}
# Get sample data
g <- get_a_random_network()
# Use a cluster algorythm to determine groups. You said you had a list. I use this to generate example data.
groups <- cluster_fast_greedy(g)
# Look at the vertecies
(V(g))
# Look at what groups they belong to:
(groups$membership)
# Here you write that you have "list of vertices of each group". You don't
# give us code, but I assume that you have data that looks like this:
CONGA_list <- lapply(1:max(groups$membership),function(x) V(g)[groups$membership ==x])
(CONGA_list)
# This is where you should really have provided a code example.
# You could convert a list like CONGA_list to a vector like this:
membership_groups <- rep(0, length(V(g)))
for(x in 1:length(CONGA_list)){
membership_groups[as.vector(CONGA_list[[x]])] <- x
}
(membership_groups == groups$membership)
# You give color to your network by first telling each vector which group it belongs to
V(g)$membership <- groups$membership
# Then we asign a color. I use a vector of R-colors which I get like this...
colors = grDevices::colors()[grep('gr(a|e)y', grDevices::colors(), invert = T)]
# ... and then I sample from them to give each vertecy a color.
colors <- sample(colors, max(V(g)$membership))
V(g)$color <- colors[V(g)$membership]
(V(g)$color)
# The plot will work with the colors in V(g)$color
plot(g, vertex.size=7, vertex.label=NA)
Good luck

R Indexing a matrix to use in plot coordinates

I'm trying to plot a temporal social network in R. My approach is to create a master graph and layout for all nodes. Then, I will subset the graph based on a series of vertex id's. However, when I do this and layout the graph, I get completely different node locations. I think I'm either subsetting the layout matrix incorrectly. I can't locate where my issue is because I've done some smaller matrix subsets and everything seems to work fine.
I have some example code and an image of the issue in the network plots.
library(igraph)
# make graph
g <- barabasi.game(25)
# make graph and set some aestetics
set.seed(123)
l <- layout_nicely(g)
V(g)$size <- rescale(degree(g), c(5, 20))
V(g)$shape <- 'none'
V(g)$label.cex <- .75
V(g)$label.color <- 'black'
E(g)$arrow.size = .1
# plot graph
dev.off()
par(mfrow = c(1,2),
mar = c(1,1,5,1))
plot(g, layout = l,
main = 'Entire\ngraph')
# use index & induced subgraph
v_ids <- sample(1:25, 15, F)
sub_l <- l[v_ids, c(1,2)]
sub_g <- induced_subgraph(g, v_ids)
# plot second graph
plot(sub_g, layout = sub_l,
main = 'Sub\ngraph')
The vertices in the second plot should match layout of those in the first.
Unfortunately, you set the random seed after you generated the graph,
so we cannot exactly reproduce your result. I will use the same code but
with set.seed before the graph generation. This makes the result look
different than yours, but will be reproducible.
When I run your code, I do not see exactly the same problem as you are
showing.
Your code (with set.seed moved and scales added)
library(igraph)
library(scales) # for rescale function
# make graph
set.seed(123)
g <- barabasi.game(25)
# make graph and set some aestetics
l <- layout_nicely(g)
V(g)$size <- rescale(degree(g), c(5, 20))
V(g)$shape <- 'none'
V(g)$label.cex <- .75
V(g)$label.color <- 'black'
E(g)$arrow.size = .1
## V(g)$names = 1:25
# plot graph
dev.off()
par(mfrow = c(1,2),
mar = c(1,1,5,1))
plot(g, layout = l,
main = 'Entire\ngraph')
# use index & induced subgraph
v_ids <- sort(sample(1:25, 15, F))
sub_l <- l[v_ids, c(1,2)]
sub_g <- induced_subgraph(g, v_ids)
# plot second graph
plot(sub_g, layout = sub_l,
main = 'Sub\ngraph', vertex.label=V(sub_g)$names)
When I run your code, both graphs have nodes in the same
positions. That is not what I see in the graph in your question.
I suggest that you run just this code and see if you don't get
the same result (nodes in the same positions in both graphs).
The only difference between the two graphs in my version is the
node labels. When you take the subgraph, it renumbers the nodes
from 1 to 15 so the labels on the nodes disagree. You can fix
this by storing the node labels in the graph before taking the
subgraph. Specifically, add V(g)$names = 1:25 immediately after
your statement E(g)$arrow.size = .1. Then run the whole thing
again, starting at set.seed(123). This will preserve the
original numbering as the node labels.
The graph looks slightly different because the new, sub-graph
does not take up all of the space and so is stretched to use
up the empty space.
Possible fast way around: draw the same graph, but color nodes and vertices that you dont need in color of your background. Depending on your purposes it can suit you.

Collapsing graph by clusters in igraph

I want to collapse a graph into its respective communities/clusters. Let me illustrate this with the following toy example:
set.seed(123)
#toy graph
g <- barabasi.game(10) %>%
as.undirected()
#identify communities
c_g <- fastgreedy.community(g)
There are three communities, as seen in the following graph.
I want to reduce the collapse the vertices so that vertices in the resulting graph correspond to the membership of the previous vertices. See the graph.
I'm new to the igraph package and I'm not familiar with the best way of dealing with igraph objects.
You could try contract:
library(igraph)
set.seed(123)
g <- barabasi.game(10) %>% as.undirected()
c_g <- fastgreedy.community(g)
V(g)$name <- letters[1:vcount(g)]
g2 <- contract(g, membership(c_g), vertex.attr.comb=toString)
par(mfrow=c(1,2))
plot(g, vertex.color=membership(c_g))
plot(simplify(g2), vertex.color=1:vcount(g2))

Resources