Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

A hack to allow arrows size in R igraph to match edge width

Tags:

plot

r

igraph

Though the manual states that this will be a future feature:

arrow.size The size of the arrows. Currently this is a constant, so it is the same for every edge. If a vector is submitted then only the first element is used, ie. if this is taken from an edge attribute then only the attribute of the first edge is used for all arrows. This will likely change in the future.

The default value is 1.

I was wondering if there was a hack around to allow the arrow size to match the edge width (each edge having its own width).

d <- data.frame(start=c("a","a","b","c"),end=c("b","b","c","b"), size=rnorm(4))


graph <- graph.data.frame(d, directed=T)

plot(graph,
     vertex.color="white",
     edge.width=E(graph)$size*20,
     edge.arrow.size=E(graph)$size)

enter image description here

like image 968
Etienne Low-Décarie Avatar asked Jun 05 '13 14:06

Etienne Low-Décarie


1 Answers

Well, there is a hack, you need to plot the graph as many times as number of different edge widths, and each time only plot the given subset of the edges, with the "right" arrow size. Use the add=TRUE argument to plot them on top of each other. Maybe you also want to plot the vertices only once.

Btw. you can submit a feature request for this at https://github.com/igraph/igraph/issues

EDIT: here is an example:

library(igraph)

## (almost) your example data
d <- data.frame(start=c("a","a","b","c"),
                end=c("b","b","c","b"),
                size=1:4)
graph <- graph.data.frame(d, directed=TRUE)

## The plotting function
eqarrowPlot <- function(graph, layout, edge.lty=rep(1, ecount(graph)),
                        edge.arrow.size=rep(1, ecount(graph)),
                        vertex.shape="circle",
                        edge.curved=autocurve.edges(graph), ...) {
  plot(graph, edge.lty=0, edge.arrow.size=0, layout=layout,
       vertex.shape="none")
  for (e in seq_len(ecount(graph))) {
    graph2 <- delete.edges(graph, E(graph)[(1:ecount(graph))[-e]])
    plot(graph2, edge.lty=edge.lty[e], edge.arrow.size=edge.arrow.size[e],
         edge.curved=edge.curved[e], layout=layout, vertex.shape="none",
         vertex.label=NA, add=TRUE, ...)
  }
  plot(graph, edge.lty=0, edge.arrow.size=0, layout=layout,
       vertex.shape=vertex.shape, add=TRUE, ...)
  invisible(NULL)
}

## Test
eqarrowPlot(graph, layout.auto(graph), edge.arrow.size=E(graph)$size/3,
            edge.width=E(graph)$size)

plot

Very wide edges look quite bad, though.

like image 89
Gabor Csardi Avatar answered Nov 15 '22 17:11

Gabor Csardi