How to scale labels in network graph based on "importance"? - r

For this project on network analysis, I'm studying communities between characters in Game Of Thrones using igraph and a handful of algorithms (walktrap, spinglass, etc). If all the labels are turned on, the plot becomes way too crowded. Is there a way to scale nodes and their labels based on the weight of their edges?
The only documentation I've been able to find is for the global resizing of labels, regardless of node importance. These are pretty simple communities -- Nodes are the names of characters, Edges are the source and target characters and the weight of each relationship.
# Walktrap algorithm
book5_walktrap = walktrap.community(book5, weights=E(book5)$weight)
plot(book5_walktrap, book5, vertex.label = NA, vertex.size=2, main="Walktrap")
# Or vertex.label = nodes$Label
Ideally, I'd like for only the most prominent characters of each community to be blown up.

You can set the size of the label using vertex.label.cex. You do not provide data nor how you are measuring importance, so I illustrate with the karate data set from igraphdata. I simply use a scaled version of degree as the importance of a node.
library(igraph)
library(igraphdata)
data(karate)
karate_walktrap = walktrap.community(karate)
set.seed(1234)
plot(karate_walktrap, karate, vertex.size=2,
main="Walktrap", vertex.label.cex=round(degree(karate)/5))

Related

Define layout for igraph layout_with_sugiyama from vertice attribute

It's my first time working with igraph - so please excuse my basic questions. I'm doing a stakeholder analysis and have different actors on different administrative scales.
I'm trying to plot my network in a hierarchical way, because I want to show the interaction between administrative boundaries.
My vertices have the attributes "name", "Label" and "Scale".
I want to plot the graph with Scale as the layers.
edges <- data.table::fread("Master_edges.csv")
nodes <- data.table::fread("Master_nodes.csv")
V(g1_2)$name <- nodes$Label
V(g1_2)$Scale <-nodes$Scale
l <- layout_with_sugiyama(layers=V(g1_2)$Scale) #this is wrong, how do I define the layers?
plot(g1_2, layout=l, vertex.label=V(g1_2), vertex.color=NA)
Also I have different types of edges - how can I plot the different edge-types in different plots?

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.

How to study the interaction between a set of nodes when the network is quite dense, using igraph?

I have 4 undirected graph with 1000 vertices and 176672, 150994, 193477, 236060 edges. I am trying to see interaction between a specific set of nodes (16 in number) for each graph. This visualization in tkplot is not feasible as 1000 vertices is already way too much for it. I was thinking of if there is some way to extract the interaction of these 16 nodes from the parent graph and view separately, which will be then more easy to handle and work with in tkplot. I don't want the loss of information as in what is the node(s) in he path of interaction if it comes from other than 16 pre-specified nodes. Is there a way to achieve it?
In such a dense graph, if you only take the shortest paths connecting each pair of these 16 vertices, you will still get a graph too large for tkplot, or even to see any meaningful on a cairo pdf plot.
However, if you aim to do it, this is one possible way:
require(igraph)
g <- erdos.renyi.game(n = 1000, p = 0.1)
set <- sample(1:vcount(g), 16)
in.shortest.paths <- NULL
for(v in set){
in.shortest.paths <- c(in.shortest.paths,
unlist(get.all.shortest.paths(g, from = v, to = set)$res))
}
subgraph <- induced.subgraph(g, unique(in.shortest.paths))
In this example, subgraph will include approx. half of all the vertices.
After this, I think you should consider to find some other way than visualization to investigate the relationships between your vertices of interest. It can be some topological metric, but it really depends on the aims of your analysis.

Coloring vertexes according to their centrality

I am trying to change the color of the vertexes in an igraph generated graph.
To be more specific, I have a 95 nodes graph created from an adjacency matrix and I would like to color them according to their degree/betweenness/eigenvalue centrality/closeness but I'm guessing that after I know how to do it with one, I'll be able to do it with others.
So I've coded the basics of graph generation until now:
dataset <- read.csv("~/Google Drive/Cours M2/Network Economics/Data/Collabs_2013.csv", sep=";")
matrix<-as.matrix(dataset)
adj<-graph.adjacency(matrix)
plot(adj)
btw<-betweenness(adj,directed = FALSE)
I now have a vector of 95 values of betweennesses and I would like to plot a graph with a gradient of colors that follows the betweenness values (e.g. from red for the lowest value to green to the highest). I'm guessing I have to mess with vertex's attributes but I have no idea how to input the vector as a color attribute.
Seems like you already did most of the work. All you have to know is colorRamppalette and setting the vertex.color for the network. Assuming you have to change the colors linearly,
just do
fine = 500 # this will adjust the resolving power.
pal = colorRampPalette(c('red','green'))
#this gives you the colors you want for every point
graphCol = pal(fine)[as.numeric(cut(btw,breaks = fine))]
# now you just need to plot it with those colors
plot(adj, vertex.color=graphCol)
credits to this. I was using a much more inefficient method to assign the colors before answering this.
Just a note:
It can be problematic to define
palette = colorRampPalette(c('blue','green'))
as the 'palette' function, is also used by igraph, and so igraph later produces as error.
See problem Color pallette for vertices in igraph network in R

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)

Resources