Aby to zrobić, używając igraph
, myślę, że musisz przekopać się w funkcję plot.igraph
, dowiedzieć się, gdzie generuje ona krzywe Beziera dla zakrzywionych krawędzi między wierzchołkami, a następnie użyć interpolacji, aby uzyskać punkty wzdłuż tych krawędzi. Dzięki tej informacji możesz rysować segmenty strzałek wzdłuż krawędzi wykresu.
Oto inne podejście, które nie jest dokładnie tym, o co prosiłeś, ale mam nadzieję, że spełni twoje oczekiwania. Zamiast igraph
, zamierzam użyć ggplot2
wraz z funkcją ggnet2
z pakietu GGally
.
Podstawowym podejściem jest uzyskanie współrzędnych punktów końcowych każdej krawędzi wykresu, a następnie interpolacja punktów wzdłuż każdej krawędzi, na której narysujemy segmenty strzałek. Zwróć uwagę, że krawędzie są liniami prostymi, ponieważ ggnet2
nie obsługuje zakrzywionych krawędzi.
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)
Oto co na wykresie wygląda następująco:
Teraz chcemy dodać strzały wzdłuż każdej krawędzi. Aby to zrobić, musimy najpierw ustalić współrzędne punktów końcowych każdej krawędzi. Możemy dostać to od samego obiektu wykresu za pomocą ggplot_build
:
gg = ggplot_build(p)
Dane wykres jest przechowywane w gg$data
:
[[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
W wyjściu powyżej, widzimy, że pierwsze cztery kolumny gg$data[[1]]
zawierają współrzędne punktów końcowych każdej krawędzi (i są one we właściwej kolejności dla skierowanego wykresu).
Teraz, gdy mamy punkty końcowe dla każdej krawędzi, możemy interpolować punkty między dwoma punktami końcowymi, w których narysujemy odcinki linii ze strzałkami na końcu. Poniższa funkcja się tym zajmuje. Pobiera ramkę danych punktów końcowych dla każdej krawędzi i zwraca listę połączeń do geom_segment
(po jednym dla każdej krawędzi wykresu), która rysuje segmenty strzałek n
.Listę połączeń geom_segment
można następnie dodać bezpośrednio do naszego oryginalnego wykresu sieciowego.
# 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"))
})
}
Teraz uruchomić funkcję, aby dodać głowice strzałek do oryginalnego grafu sieci
p = p + add.arrows(gg$data[[1]], 15)
A oto co na wykresie wygląda następująco:
w podobnym duchu do eipi miło odpowiedź, można użyć Rgraphviz zapisać wykres, który umożliwia łatwe wydobycie pozycje krzywej węzła i beziera, zamień na ggplot (patrz [tutaj] (http://stackoverflow.com/questions/40668022/plott-a-dag-in-a-dot-layout-using-ggnet/41204088#41204088)) a następnie dodaj strzałki, jak w odpowiedzi eipi. – user20650