9

I am trying to plot small networks using igraph in R. Each vertex in the network has a name, which is equivalent to its label. I would like to make each vertex have a rectangular symbol that is just large enough to fit its label.

This is my main inspiration.

Map of Hyperboria

What is the best way to do this with igraph?

Edit: more information

The code is here

jsonToNM <- function(jfile, directed=TRUE) {
  # Requires "rjson" and "igraph"

  nm.json <- fromJSON(file=jfile)
  nm.graph <- c()

  # Initialize the graph with the given nodes
  g <- graph.empty(n=length(nm.json), directed=directed)
  # Add their names
  V(g)$name <- names(nm.json)
  V(g)$label <- V(g)$name

  # Now, add the edges
  for(i in 1:length(nm.json)) {
    # If the node has a "connected" field,
    # then we note the connections by looking
    # the names up.
    if(length(nm.json[[i]]$connected > 0)) {
      for(j in 1:length(nm.json[[i]]$connected)) {
        # Add the entry
        g <- g + edge(names(nm.json)[i],
                        nm.json[[i]]$connected[j])
      }
    }
  }

  plot(g, vertex.label.dist=1.5)
}

And the current output is below.

current output

My goal is to place the labels inside of the vertex graphic, and expand the width of the vertex to accommodate the label.

Alexander Bauer
  • 10,663
  • 8
  • 29
  • 40
  • Do you think you could show a reproducible example of your input, and how you've created graphs so far (that presumably don't have the right-looking vertices)? You could use `dput` to provide the data. – David Robinson Jan 23 '13 at 03:51
  • That is not a reproducible example. I don't have `jfile`. – Gabor Csardi Jan 23 '13 at 06:19

2 Answers2

11

Here is an example. Among some dirty tricks (i.e. multiplying the vertex size by 200), the key is to use two plot commands, so that we can measure the width (and height) of the labels with strwidth(), after the plot size is set with the first (empty) plot.

library(igraph)
camp <- graph.formula(Harry:Steve:Don:Bert - Harry:Steve:Don:Bert,
                      Pam:Brazey:Carol:Pat - Pam:Brazey:Carol:Pat,
                      Holly   - Carol:Pat:Pam:Jennie:Bill,
                      Bill    - Pauline:Michael:Lee:Holly,
                      Pauline - Bill:Jennie:Ann,
                      Jennie  - Holly:Michael:Lee:Ann:Pauline,
                      Michael - Bill:Jennie:Ann:Lee:John,
                      Ann     - Michael:Jennie:Pauline,
                      Lee     - Michael:Bill:Jennie,
                      Gery    - Pat:Steve:Russ:John,
                      Russ    - Steve:Bert:Gery:John,
                      John    - Gery:Russ:Michael)

V(camp)$label <- V(camp)$name
set.seed(42)   ## to make this reproducable
co <- layout.auto(camp)

plot(0, type="n", ann=FALSE, axes=FALSE, xlim=extendrange(co[,1]), 
     ylim=extendrange(co[,2]))
plot(camp, layout=co, rescale=FALSE, add=TRUE,
     vertex.shape="rectangle",
     vertex.size=(strwidth(V(camp)$label) + strwidth("oo")) * 100,
     vertex.size2=strheight("I") * 2 * 100)

igraph vertex label width

Btw. this does not really work well with SVG graphics, because there is no way to measure the width of the text from R, the SVG device only makes guesses.

Gabor Csardi
  • 10,705
  • 1
  • 36
  • 53
1

I know that this is not a direct answer to your question but I would suggest to use a different tool for visualization. yEd is very good at adjusting the nodes' width to the label's size. You can also manipulate the visualization easily, and export it to SVG for a final polish. It can be obtained for free from www.yworks.com (Disclaimer: I am not working there).

To export the graph in a well-readable format (yEd does not understand igraph's gml-format), use graphml:

write.graph(graph, "test.graphml", format="graphml")

Open it in yEd. Go to edit-> properties mapper and click on "new configuration (Node)" (the green "plus" symbol, upper left). In the middle of the fram, under "data source", search for the name of your labels (should be 'name'). In the middle tab called "map to" choose "label text" and in the right column leave the "conversion" be set to "Automatic".

Now choose Tools -> fit node to label (the default parameters are fine for a first try) and then choose your favourite layout. You can export to various image-formats but to my knowledge all are implemented using a bitmap-intermediate. Thus, I normally export to SVG and do the polishing in inkscape. If anyone knows a more efficient procedure to get good-looking layouts of medium-sized graphs produced in igraph, let me know.

networker
  • 117
  • 1
  • 8