18

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

Etienne Low-Décarie
  • 13,063
  • 17
  • 65
  • 87

1 Answers1

13

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.

Gabor Csardi
  • 10,705
  • 1
  • 36
  • 53
  • I just tried this out and have a few issues. When I try it with the example I gave, it throws an error. Example code:`d <- data.frame(start=c("a","a","b","c"),end=c("b","b","c","b"), size=rnorm(4)) for(i in 1:nrow(d)){ graph <- graph.data.frame(d[1,], directed=T) plot.new() plot(graph, vertex.color="white", edge.width=E(graph)$size*20, edge.arrow.size=E(graph)$size, add=T) }` If I try with my own data (which also contains the coordinates of the vertex, one one of vertices plotted in each loop. Is there a way to plot all vertices and then select each edge one at a time? – Etienne Low-Décarie Jun 05 '13 at 22:00
  • 1
    @EtienneLow-Décarie: added an example. – Gabor Csardi Jun 06 '13 at 03:10
  • @GaborCsardi Beautiful. I think iGraph isn't particularly flexible when it comes to this. – victor_v Sep 06 '17 at 14:44