R reciprocal edges in igraph in R - r

I am working with graphs in R. I am currently using igraph and I would like to be able to plot bidirectional edges "reciprocal edges" of a graph. So far I've seen it is possible to plot "bidirectional" graphs but not reciprocal edges, for example: E(1,3) and E(3,1) could potentially be represented as a bidirectional edge <-->, but instead I would like to plot two parallel edges one pointing to the opposite direction of the other || .
There exist in Rgraphviz an option when plotting "plot(rEG, recipEdges = "distinct")" that makes this, but I like more how plots look like on igraph. Thanks in advance.

In igraph, you can use the edge attribute curved to curve the edges you want.
For example, here is a graph based small adjacency matrix:
library("igraph")
adj <- matrix(c(
0,1,1,
1,0,1,
0,0,0),3,3,byrow=TRUE)
library("igraph")
G <- graph.adjacency(adj)
The edge between node 0 and 1 is bidirected (Actually, it isn't, it are two edges and they just look like a bidirected edge because they are straight).:
plot(G)
To change this, we can use the edgelist:
E <- t(apply(get.edgelist(G),1,sort))
E(G)$curved <- 0
E(G)[duplicated(E) | duplicated(E,fromLast =TRUE)]$curved <- 0.2
plot(G)
Another option is my package, where this is the default behavior:
library("qgraph")
qgraph(adj)
which can be suppressed with the bidirectional argument.

Try plot(graph, edge.curved=TRUE). It definitely works in igraph 0.6, and it may also work in igraph 0.5.4 (not sure when it was added).

Related

Automatically curving an arc when it is overlapping with another one

I am automatically generating graphs whose nodes need to be in fixed positions. For example:
There is actually an arc from node V4 to node V16, but we annot see it because there are also arcs from V4 to V10 and from V10 to V16.
Note that both the nodes and the arcs are generated automatically, and that the positions may vary, so I would need an automated way to curve arcs that are hidden behind other arcs.
Also note that none of these solutions are valid: igraph: Resolving tight overlapping nodes ; Using igraph, how to force curvature when arrows point in opposite directions. The first one simply places de nodes in a certain way, but my nodes need to be fixed. The second one simply deals with pairs of nodes that have two arcs connecting them going in the opposite direction.
UPDATE: The construction of the graph is the result of the learning process of the graph that forms a Bayesian Network using bnlearn library, so I am not very sure how could I produce a reproducible example. The positions of the nodes are fixed because they represent positions. I actually need some magic, some kind of detection of overlapping arcs: If two arcs overlap, curve one of them slightly so that it can be seen. I know from the linked questions that curving an arc is an option, so I thought maybe this kind of magic could be achieved
One solution would be to use the qgraph package. In the example below it automatically curves the bidirectional edges:
library(igraph)
library(qgraph)
# the raster layout
layout <- cbind(1:3, rep(1:3, each = 3))
# fully connected network
adj <- matrix(1, 9, 9)
# plot directed and undirected network
layout(matrix(1:2, 1, 2))
qgraph(adj, layout = layout, directed = FALSE, title = "undirected")
qgraph(adj, layout = layout, directed = TRUE, title = "directed") # automatically curves the bidirectional arrows
To convert an igraph object to something qgraph can use, all you need is an edgelist or adjacency matrix:
g <- make_ring(9)
edgeList <- do.call(rbind, igraph::get.adjedgelist(g))
qgraph(edgeList)
If you also want to include the axes, you can do so using axis() since qgraph uses base graphics. However, you probably have to tinker with par() as well to make it look nice.

Making igraph clearer to read

I have a directed igraph with 69 vertices, shown below. It was plotted using the igraph package:
library(igraph)
ig <- graph.adjacency(data, mode="directed", weighted=TRUE)
plot(ig)
I'm looking to achieve the following 2 things:
(a) Space the vertices out and maybe lengthen the edges to make it a little easier to read
(b) In reality, my labels are longer. Is it possible to make a vertex bigger and the text smaller to accommodate this.
Any ideas?
Here is my data: https://www.dropbox.com/s/rtedrd1x1duqllj/data.Rdata?dl=0
All of the parameters are definitely highly customizable. I substituted state names for your vertex labels:
# this ensures the starting random position is the same
# for the layouts that use a random starting position
set.seed(1492)
l <- layout.fruchterman.reingold(ig, niter=5000, area=vcount(ig)^4*10)
plot(ig, layout=l,
edge.arrow.size=0.5,
vertex.label.cex=0.75,
vertex.label.family="Helvetica",
vertex.label.font=2,
vertex.shape="circle",
vertex.size=1,
vertex.label.color="black",
edge.width=0.5)
You shld rly take some time to read help("igraph.plotting") & help("layout")

Graph Visualization with igraph and R

I am trying to visualize graphs in R with the igraph package. I wish to visualize graphs with the edge size being between 2000 to 70,000. The plots look like this:
This is not a nice plot as you cannot see anything. I have figured out how to take away the labels, but still you cannot see anything since the vertices are so big.
Can I remove the vertices and just look at the edges?
For example here is the same plot but I took the picture before it was finished. It seems that R only draws the edges before it is finished:
You can set the vertex size to 0.
library(igraph)
g <- barabasi.game(100)
plot( g, vertex.size=0, vertex.label=NA, edge.arrow.size=0 )

Force-directed graph drawing: Edit the force between specific nodes (R)

I want to analyse a social network using the R packages statnet and/or igraph in reference to force-directed graph drawing (kamada.kawai/fruchterman.reingold). I wounder, if it is possible to adjust the "force" between 2 specific nodes, e.g. to consider a larger or smaller cooperation between 2 stakeholders. However, i do not want to edit the general force between all nodes
(as proposed here:)
How do I lengthen edges in an igraph network plot (layout=fruchterman.reingold)?
The idea on this would be to get a more realistic image of a social network, also for further analysis.
Thanks a lot and nice weekend to everybody!
This layout algorithm supports edge weights, which are basically used as multipliers for the attraction forces along the edges. I.e. edges with high weight will tend to be shorter. Here is a simple example
library(igraph)
g <- graph.ring(10)
# Edge weights, will be recycled
E(g)$weight <- c(1,4)
coords <- layout.fruchterman.reingold(g, weights=E(g)$weight)
# Eliminate the margin
par(mar=c(0,0,0,0))
plot(g, layout=coords, vertex.color="#E495A5", vertex.size=20)

Draw Network in R (control edge thickness plus non-overlapping edges)

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

Resources