2017-01-19 4 views
14

Ich hoffe, ein gerichtetes Netzwerk Grundstück mit Pfeilspitzen (oder ähnlich Chevrons) entlang der Länge der Linie zu machen ...Custom Stil für Netzwerk-Graph in R

enter image description here

Die igraph Bibliothek scheint Verwenden Sie die Basisfunktion polygon, die lty akzeptiert, um Linientypen anzugeben, diese sind jedoch auf verschiedene Bindestriche beschränkt.

Gibt es eine Möglichkeit individuelle Symbole zu machen (oder sogar die Dreiecke in pch verwendet wird) eine Linie in R zu bilden?

Minimal-Code um die Grafik zu machen:

require(igraph) 
gr = graph_from_literal(A -+ B -+ C) 
plot(gr,edge.curved=TRUE) 

BTW, würde ich eine andere Netzwerkanalyse-Bibliothek in Ordnung zu verwenden, wenn sie dies unterstützen würden. Ich fragte den Entwickler von ggraph und er sagte, dass es nicht gemacht werden könnte, das zu tun.

+0

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

Antwort

7

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:

enter image description here

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:

enter image description here

9

Cytoscape und RCy3 Bibliotheken werden zum Erstellen von Netzwerkdiagrammen verwendet.

Installieren Sie cytoscape Version 3 und höher from here. Starten Sie dann die cytoscape GUI (grafische Benutzeroberfläche) Sitzung.

Versionen in dieser Antwort verwendet werden, sind Cytoscape:3.4.0 und RCy3:1.5.2

OS: Windows-7

# load libraries 
library('RCy3') 

# create cytoscape connection 
cy <- RCy3::CytoscapeConnection() 
RCy3::deleteAllWindows(cy)  # delete all windows in cytoscape 
hideAllPanels(cy)    # hide all panels 

# create node and edge data and create graphNEL object 
node.tbl <- data.frame(Node.Name = c('A', 'B', 'C')) 
edge.tbl <- data.frame(Gene.1 = c('A', 'B'), 
         Gene.2 = c('B', 'C')) 
g <- cyPlot(node.tbl, edge.tbl) 
g 
# A graphNEL graph with directed edges 
# Number of Nodes = 3 
# Number of Edges = 2 

# create cytoscape window and display the graph 
window_title <- 'example' 
cw <- RCy3::CytoscapeWindow(window_title, graph=g, overwrite=FALSE) 
RCy3::displayGraph(cw) 

# set visual style and layout algorithm 
vis_style <- 'Curved'    # getVisualStyleNames(cw)[7] 
RCy3::setVisualStyle(cw, vis_style)  
RCy3::layoutNetwork(obj = cw, layout.name = "circular") 
RCy3::layoutNetwork(obj = cw, layout.name = "kamada-kawai") 

# get all edges 
getAllEdges(cw) 
# [1] "A (unspecified) B" "B (unspecified) C" 

# get cytoscape supported line types 
supported_styles <- getLineStyles (cw) 
supported_styles 
# [1] "EQUAL_DASH"  "PARALLEL_LINES" "MARQUEE_DASH"  "MARQUEE_EQUAL" "SOLID"   "FORWARD_SLASH" "DASH_DOT"   "MARQUEE_DASH_DOT" 
# [9] "SEPARATE_ARROW" "VERTICAL_SLASH" "DOT"    "BACKWARD_SLASH" "SINEWAVE"   "ZIGZAG"   "LONG_DASH"  "CONTIGUOUS_ARROW" 

# set edge line type 
setEdgeLineStyleDirect(cw, "A (unspecified) B", supported_styles [16]) # "CONTIGUOUS_ARROW" 

enter image description here

setEdgeLineStyleDirect(cw, "A (unspecified) B", supported_styles [9]) # "SEPARATE_ARROW" 

enter image description here

# save network as image in the current working directory 
fitContent (cw) 
setZoom(cw, getZoom(cw) - 1) # adjust the value from 1 to a desired number to prevent cropping of network diagram 
saveImage(obj = cw, 
      file.name = 'example', 
      image.type = 'png', 
      h = 700) 

Für weitere Informationen, lesen Sie ?RCy3::setEdgeLineStyleDirect.

Auch für Cytoscape Ränder Attribute finden here

installieren RCy3:

# Install RCy3 - Interface between R and Cytoscape (through cyRest app) 
library('devtools') 

remove.packages("BiocInstaller") 
source("https://bioconductor.org/biocLite.R") 
biocLite("BiocGenerics") 
biocLite("bitops") 
install_github("tmuetze/Bioconductor_RCy3_the_new_RCytoscape") 
+0

Sehr kreativ, obwohl ich nicht sicher bin, ob ich Cytoscape für diesen Zweck verwenden würde. – beroe