I am brand new to R and I am using library (grid), (graph), (Rgraphviz) and gRbase to try make a Undirected Graph for calculating marginal probability of each node and running the sum product algorithm on all the nodes.
This is my graph:
g1 <- ug(~1:2 + 1:3 + 2:4 + 2:5) and it looks pretty when I plot(g1). The problem is I have no idea how to input the node potentials and pairwise potentials onto the graph in R nor how to code up the sum-product algorithm in R. Any help or a reference to help would be appreciated. Thanks.
Related
I have a weighted directed adjacency matrix and I am trying to plot a graph visualization using PlotRecipes.jl. I can't seem to find a way to show both the nodes with labels and somehow represent the edge weights on the edges. I have tried...
graphplot(G, weights=weights,names=names)
where G is the adjacency matrix, weights are the edge weights and names is a list of names for the nodes, but I get this output
using just
graphplot(G,names=names)
I get the same output.
Is there any way to do this with PlotRecipes.jl or is there possibly another library?
You can represent the weights with color (using the line_z keyword), but not with line thickness at the moment. cf https://github.com/JuliaPlots/PlotRecipes.jl/issues/39
We have an non square adjacency matrix p (197x190)matrix without weights (only 1 if the 2 telephone numbers have called with each other and 0 otherwise). We tried to visualize this with a graph using this simple code and the igraph package:
p<-as.matrix(dcast(SNA_data, A_NUMBER~B_NUMBER, value.var="W", fill=0))[,]
graph<-graph.adjacency(p, mode="undirected", weighted=NULL)
plot(graph)
The result is a very small graph in plot that is totally unreadable graph anybody knows how to solve this?
Thanks in advance.
Try to use x11() to plot your graph in an external window :
library(igraph)
adjm1<-matrix(sample(0:1,1000,replace=TRUE,prob=c(0.9,01)),nc=10)
g1<-graph.adjacency(adjm1)
x11()
plot(g1)
Reference for the simulation : using graph.adjacency() in R
If your matrix is not a square, it might be worth trying an incidence matrix. By default the matrix is directed from rows to columns.
# create the network object
network <- graph_from_incidence_matrix(p)
network
class(network)
# plot it
plot(network)
I have an interaction network and I used the following code to make an adjacency matrix and subsequently calculate the dissimilarity between the nodes of the network and then cluster them to form modules:
ADJ1=abs(adjacent-mat)^6
dissADJ1<-1-ADJ1
hierADJ<-hclust(as.dist(dissADJ1), method = "average")
Now I would like those modules to appear when I plot the igraph.
g<-simplify(graph_from_adjacency_matrix(adjacent-mat, weighted=T))
plot.igraph(g)
However the only thing that I have found thus far to translate hclust output to graph is as per the following tutorial: http://gastonsanchez.com/resources/2014/07/05/Pretty-tree-graph/
phylo_tree = as.phylo(hierADJ)
graph_edges = phylo_tree$edge
graph_net = graph.edgelist(graph_edges)
plot(graph_net)
which is useful for hierarchical lineage but rather I just want the nodes that closely interact to cluster as follows:
Can anyone recommend how to use a command such as components from igraph to get these clusters to show?
igraph provides a bunch of different layout algorithms which are used to place nodes in the plot.
A good one to start with for a weighted network like this is the force-directed layout (implemented by layout.fruchterman.reingold in igraph).
Below is a example of using the force-directed layout using some simple simulated data.
First, we create some mock data and clusters, along with some "noise" to make it more realistic:
library('dplyr')
library('igraph')
library('RColorBrewer')
set.seed(1)
# generate a couple clusters
nodes_per_cluster <- 30
n <- 10
nvals <- nodes_per_cluster * n
# cluster 1 (increasing)
cluster1 <- matrix(rep((1:n)/4, nodes_per_cluster) +
rnorm(nvals, sd=1),
nrow=nodes_per_cluster, byrow=TRUE)
# cluster 2 (decreasing)
cluster2 <- matrix(rep((n:1)/4, nodes_per_cluster) +
rnorm(nvals, sd=1),
nrow=nodes_per_cluster, byrow=TRUE)
# noise cluster
noise <- matrix(sample(1:2, nvals, replace=TRUE) +
rnorm(nvals, sd=1.5),
nrow=nodes_per_cluster, byrow=TRUE)
dat <- rbind(cluster1, cluster2, noise)
colnames(dat) <- paste0('n', 1:n)
rownames(dat) <- c(paste0('cluster1_', 1:nodes_per_cluster),
paste0('cluster2_', 1:nodes_per_cluster),
paste0('noise_', 1:nodes_per_cluster))
Next, we can use Pearson correlation to construct our adjacency matrix:
# create correlation matrix
cor_mat <- cor(t(dat))
# shift to [0,1] to separate positive and negative correlations
adj_mat <- (cor_mat + 1) / 2
# get rid of low correlations and self-loops
adj_mat <- adj_mat^3
adj_mat[adj_mat < 0.5] <- 0
diag(adj_mat) <- 0
Cluster the data using hclust and cutree:
# convert to dissimilarity matrix and cluster using hclust
dissim_mat <- 1 - adj_mat
dend <- dissim_mat %>%
as.dist %>%
hclust
clusters = cutree(dend, h=0.65)
# color the nodes
pal = colorRampPalette(brewer.pal(11,"Spectral"))(length(unique(clusters)))
node_colors <- pal[clusters]
Finally, create an igraph graph from the adjacency matrix and plot it using the fruchterman.reingold layout:
# create graph
g <- graph.adjacency(adj_mat, mode='undirected', weighted=TRUE)
# set node color and plot using a force-directed layout (fruchterman-reingold)
V(g)$color <- node_colors
coords_fr = layout.fruchterman.reingold(g, weights=E(g)$weight)
# igraph plot options
igraph.options(vertex.size=8, edge.width=0.75)
# plot network
plot(g, layout=coords_fr, vertex.color=V(g)$color)
In the above code, I generated two "clusters" of correlated rows, and a third group of "noise".
Hierarchical clustering (hclust + cuttree) is used to assign the data points to clusters, and they are colored based on cluster membership.
The result looks like this:
For some more examples of clustering and plotting graphs with igraph, checkout: http://michael.hahsler.net/SMU/LearnROnYourOwn/code/igraph.html
You haven't shared some toy data for us to play with and suggest improvements to code, but your question states that you are only interested in plotting your clusters distinctly - that is, graphical presentation.
Although igraph comes with some nice force directed layout algorithms, such as layout.fruchterman.reingold, layout_with_kk, etc., they can, in presence of a large number of nodes, quickly become difficult to interpret and make sense of at all.
Like this:
With these traditional methods of visualising networks,
the layout algorithms, rather than the data, determine the visualisation
similar networks may end up being visualised very differently
large number of nodes will make the visualisation difficult to interpret
Instead, I find Hive Plots to be better at displaying important network properties, which, in your instance, are the cluster and the edges.
In your case, you can:
Plot each cluster on a different straight line
order the placement of nodes intelligently, so that nodes with certain properties are placed at the very end or start of each straight line
Colour the edges to identify direction of edge
To achieve this you will need to:
use the ggnetwork package to turn your igraph object into a dataframe
map your clusters to the nodes present in this dataframe
generate coordinates for the straight lines and map these to each cluster
use ggplot to visualise
There is also a hiveR package in R, should you wish to use a packaged solution. You might also find another visualisation technique for graphs very useful: BioFabric
I built a graph using bnlearn:hc using the following steps:
bootstrap 500 bns using hc algorithm
calculated the best threshold
extract the best arcs with threshold > "best threshold calculated" and direction > 0.5
So if I try to bootstrap with 1 bn, to be more fast in small tests, sometimes I have some undirected arcs.
In bnlearn how I can know what are the undirected arcs from a bn object (a learned structure) and remove it? This would be the best solution ?
Tks
When there are many nodes it can be hard to pick out the undirected arcs in a graph. In this case you can use undirected.arcs() to find them.
Usage is as follows:
boot = boot.strength(data = df, R=500, algorithm = 'hc',
algorithm.args = list(score = 'bde'))
boot.avg = averaged.network(boot)
undirected.arcs(boot.avg)
You can check the scores of each arc direction to make sure one isn't greater than the other:
score(set.arc(boot.avg, from="A", to="B", df)
score(set.arc(boot.avg, from="B", to="A", df)
And then finally you will want to set a direction like so:
boot.avg = set.arc(boot.avg, from="A", to="B")
If you want to remove the arc entirely you can do so with:
boot.avg = drop.arc(boot.avg, from="A", to="B")
To see which arcs are undirected you can plot the network. Use plot(network) or, if you have the package Rgraphviz, you can use graphviz.plot(network).
I have a graph containing 16809 nodes an 173,393 edges. Now i want to generate a geometric random graph with same number of nodes and edges in r. How can I achieve that.
My example R script is as follows.
library(igraph)
g2 <- graph.formula(A:B - A:C, B:D - C:D , D:F - D:F )
g2
Then how can I model g2 in geometric random graph. Is there any function to create this random graphs in R.
There is a function to generate GRG by known radius and number of nodes, see sample_grg. But the concept of GRGs means that nodes are placed randomly, so the number of edges will be random. The following code gives pretty close results to what you need:
g <- sample_grg(16809, 0.02)
But I don't think there is a way to somehow determine the number of edges.