Um dies mit igraph
zu tun, denke ich, müssten Sie in die plot.igraph
Funktion graben, herauszufinden, wo es die Bezier-Kurven für die gekrümmten Kanten zwischen Scheitelpunkte generiert und dann Interpolation verwenden, um Punkte entlang dieser Kanten zu erhalten. Mit diesen Informationen könnten Sie Pfeilsegmente entlang der Kanten des Diagramms zeichnen.
Hier ist ein anderer Ansatz, der nicht genau das ist, wonach Sie gefragt haben, aber ich hoffe, dass er Ihren Anforderungen entspricht. Anstelle von igraph
werde ich ggplot2
zusammen mit der ggnet2
Funktion aus dem GGally
Paket verwenden.
Der grundlegende Ansatz besteht darin, die Koordinaten der Endpunkte jeder Graphenkante zu erhalten und dann Punkte entlang jeder Kante zu interpolieren, an der wir Pfeilsegmente zeichnen. Beachten Sie, dass die Kanten gerade Linien sind, da ggnet2
keine gekrümmten Kanten unterstützt.
library(ggplot2)
library(GGally)
# Create an adjacency matrix that we'll turn into a network graph
m = matrix(c(0,1,0,0,
0,0,1,0,
1,0,0,1,
0,0,0,0), byrow=TRUE, nrow=4)
# Plot adjacency matrix as a directed network graph
set.seed(2)
p = ggnet2(network(m, directed=TRUE), label=TRUE, arrow.gap=0.03)
Hier ist, was die Grafik wie folgt aussieht:
Jetzt wollen wir entlang jeder Kante Pfeile hinzuzufügen. Um dies zu tun, müssen wir zuerst die Koordinaten der Endpunkte jeder Kante herausfinden. Das können wir aus dem Diagramm Objekt erhalten selbst ggplot_build
mit:
gg = ggplot_build(p)
Die Grafik-Daten in gg$data
gespeichert ist:
[[1]]
x xend y yend PANEL group colour size linetype alpha
1 0.48473786 0.145219576 0.29929766 0.97320807 1 -1 grey50 0.25 solid 1
2 0.12773544 0.003986273 0.97026602 0.04720945 1 -1 grey50 0.25 solid 1
3 0.02670486 0.471530869 0.03114479 0.25883640 1 -1 grey50 0.25 solid 1
4 0.52459870 0.973637028 0.25818813 0.01431760 1 -1 grey50 0.25 solid 1
[[2]]
alpha colour shape size x y PANEL group fill stroke
1 1 grey75 19 9 0.1317217 1.00000000 1 1 NA 0.5
2 1 grey75 19 9 0.0000000 0.01747546 1 1 NA 0.5
3 1 grey75 19 9 0.4982357 0.27250573 1 1 NA 0.5
4 1 grey75 19 9 1.0000000 0.00000000 1 1 NA 0.5
[[3]]
x y PANEL group colour size angle hjust vjust alpha family fontface lineheight label
1 0.1317217 1.00000000 1 -1 black 4.5 0 0.5 0.5 1 1 1.2 1
2 0.0000000 0.01747546 1 -1 black 4.5 0 0.5 0.5 1 1 1.2 2
3 0.4982357 0.27250573 1 -1 black 4.5 0 0.5 0.5 1 1 1.2 3
4 1.0000000 0.00000000 1 -1 black 4.5 0 0.5 0.5 1 1 1.2 4
In der Ausgabe oben, können wir sehen, dass Die ersten vier Spalten von gg$data[[1]]
enthalten die Koordinaten der Endpunkte jeder Kante (und sie sind in der richtigen Reihenfolge für den gerichteten Graphen).
Jetzt, da wir die Endpunkte für jede Kante haben, können wir Punkte zwischen den beiden Endpunkten interpolieren, an denen wir Liniensegmente mit Pfeilen am Ende zeichnen. Die folgende Funktion kümmert sich darum. Er nimmt einen Datenrahmen von Endpunkten für jede Kante und gibt eine Liste von Aufrufen an geom_segment
(eine für jede Graphenkante) zurück, die n
Pfeilsegmente zeichnet.Diese Liste der geom_segment
Aufrufe kann dann direkt zu unserem ursprünglichen Netzwerkgraphen hinzugefügt werden.
# Function that interpolates points between each edge in the graph,
# puts those points in a data frame,
# and uses that data frame to return a call to geom_segment to add the arrow heads
add.arrows = function(data, n=10, arrow.length=0.1, col="grey50") {
lapply(1:nrow(data), function(i) {
# Get coordinates of edge end points
x = as.numeric(data[i,1:4])
# Interpolate between the end points and put result in a data frame
# n determines the number of interpolation points
xp=seq(x[1],x[2],length.out=n)
yp=approxfun(x[c(1,2)],x[c(3,4)])(seq(x[1],x[2],length.out=n))
df = data.frame(x=xp[-n], xend=xp[-1], y=yp[-n], yend=yp[-1])
# Create a ggplot2 geom_segment call with n arrow segments along a graph edge
geom_segment(data=df, aes(x=x,xend=xend,y=y,yend=yend), colour=col,
arrow=arrow(length=unit(arrow.length,"inches"), type="closed"))
})
}
Nun wollen wir die Funktion ausführen, um die Pfeilspitzen auf die ursprüngliche Netzwerkgraphen
p = p + add.arrows(gg$data[[1]], 15)
Und hier hinzufügen ist, was der Graph wie folgt aussieht:
in ähnlicher Weise der schöne Antwort auf eipi, könnten Sie Rgraphviz verwenden, um die Grafik zu speichern, die von einfacher Extraktion erlaubt Knoten- und Bezierkurvenpositionen, konvertieren zu ggplot (siehe [hier] (http://stackoverflow.com/questions/40668022/plott-a-dag-in-a-dot-layout-using-ggnet/41204088#41204088)) und fügen Sie dann Pfeile wie in Eipis Antwort hinzu. – user20650