3

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.

fraxture
  • 5,113
  • 4
  • 43
  • 83
  • When I run your code I get an error `Error in text.default(x, y, labels = labels, col = label.color, family = label.family, : zero-length 'labels' specified`. I'm not sure if the problem is on my end or if there's something missing from you code. If you start a clean session, does the code you posted run without error on your system? – eipi10 Aug 17 '16 at 17:41
  • There was a typo in the fourth line which I fixed. Try again. Also, of course, your data might be in a different location in the first line. – fraxture Aug 18 '16 at 06:05
  • Data location wasn't an issue. I'll let you know if I come up with a fix. – eipi10 Aug 18 '16 at 06:23
  • Thanks, maybe we could chat about it together as well? Curiosu to know what approach you'd take. – fraxture Aug 18 '16 at 07:14

1 Answers1

10

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

eipi10
  • 91,525
  • 24
  • 209
  • 285