Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Increasing spaces between vertices for R iGraph

I am working on a visualization of political books purchased together on Amazon using R and igraph. I've been able to get the network graph in a form that reveals the way certain books fall in a position indicating that they were not only purchased by people just buying other books with the same political point of view. Here's the graph:

My problem is that with all those books in the tighter clusters, it's pretty impossible to read the labels. I'd like to expand those clusters if I could without obscuring the middle-position of the few titles linking the clusters.

Does anyone have any ideas about how I might get this done?

In order to generate this graph, I read in this data as a gml file and then did the following:

g<-read.graph("data/polbooks/polbooks.gml", format=c("gml"))
V(g)$degree <- degree(g, mode="all")
cut.off <- mean(V(g)$degree)
sub <- induced_subgraph(g, which(V(g)$degree>cut.off))
plot(sub, vertex.shape="none", vertex.size=1,     
     vertex.label.color=ifelse(V(sub)$value=="l", "blue", "red"),   
     layout=layout_with_fr)

I've tried several of the built-in layouts, but none of them really produce the desired result.

like image 729
fraxture Avatar asked Sep 05 '25 03:09

fraxture


1 Answers

Here's what I've done in an attempt to improve the readability of the graph:

  1. Wrapped long book titles.

  2. Shrunk the font size.

  3. Set a seed so that layouts are reproducible, allowing you to keep "random" layouts that you like.

  4. Used graph layout code from another SO answer to increase node separation.

Here is the implementation:

## Function to wrap long strings
# Source: http://stackoverflow.com/a/7367534/496488
wrap_strings <- function(vector_of_strings,width){
  as.character(sapply(vector_of_strings, FUN=function(x){
                        paste(strwrap(x, width=width), collapse="\n")
                        }))
  }

# Apply the function to wrap the node labels
V(sub)$label = wrap_strings(V(sub)$label, 12)

## Shrink font
V(sub)$label.cex = 0.8

# Function to increase node separation (for explanatory details, see the link below)
# Source: http://stackoverflow.com/a/28722680/496488
layout.by.attr <- function(graph, wc, cluster.strength=1,layout=layout.auto) {  
  g <- graph.edgelist(get.edgelist(graph)) # create a lightweight copy of graph w/o the attributes.
  E(g)$weight <- 1

  attr <- cbind(id=1:vcount(g), val=wc)
  g <- g + vertices(unique(attr[,2])) + igraph::edges(unlist(t(attr)), weight=cluster.strength)

  l <- layout(g, weights=E(g)$weight)[1:vcount(graph),]
  return(l)
}

## Make layout reproducible. Different values will produce different layouts,
##  but setting a seed will allow you to reproduce a layout if you like it.
set.seed(3)

Now let's plot the graph:

plot(sub, vertex.shape="none", vertex.size=1,     
     vertex.label.color=ifelse(V(sub)$value=="l", "blue", "red"),
     layout=layout.by.attr(sub, wc=1))

enter image description here

like image 162
eipi10 Avatar answered Sep 08 '25 00:09

eipi10