2015-08-03 11 views
11

ich eine Grafik generiert haben:Zeichnung manuell auf eine Figur

library(DiagrammeR) 
grViz(" 
digraph boxes_and_circles { 

    # a 'graph' statement 
    graph [layout = neato, overlap = true, fontsize = 10, outputorder = edgesfirst] 

    # several 'node' statements 
    node [shape = circle, 
    fontname = Helvetica] 
    A [pos = '1,1!']; 
    B [pos = '0,2!']; 
    C [pos = '1.5,3!']; 
    D [pos = '2.5,1!']; 
    E [pos = '4,1!']; 
    F [pos = '4,2!']; 
    G [pos = '5,1!']; 
    H [pos = '6,2!']; 
    I [pos = '1.5,-0.1!']; 

    # several 'edge' statements 
    A->B B->C 
    D->E D->F E->F E->G F->G G->H F->H 
    } 
    ") 

Welche produziert:

enter image description here

nun den Knoten A einen Kasten mit gestrichelten Linien ziehen um Ich möchte, B und C.

Wie kann ich dies in R erreichen? Eine Schlüsselanforderung der Lösung ist, dass sie reproduzierbar ist, d. H. Dass ich das Skript mehrere Male ausführen kann und dasselbe Ergebnis erhalten kann.

+1

tun Sie es wollen – rawr

+0

@rawr ein Widget oder einfach nur ein Bild sein: Was ist der Unterschied? Am Ende muss ich ein Bild ausgeben, um es in ein Word-Dokument einzufügen. – histelheim

+0

@histelheim Vielleicht könnten Sie versuchen, ein Rechteck manuell als Knoten zu positionieren, indem Sie 'engine =" neato "' (statt circo) und das 'pos'-Attribut verwenden:' a [pos = '-3,4!', Width = 3,5, Höhe = 0,5, Form = Rechteck, Label = ''] '. Werfen Sie einen Blick auf http://www.graphviz.org/content/attrs#dpos http://stackoverflow.com/questions/5343899/ und http://stackoverflow.com/questions/29208525/ –

Antwort

6

Hier ist ein weiterer Ansatz, der auf IGRAPH. Es ist inspiriert von dieser Inschrift code sample.

Ich gehe davon aus, dass die Verwendung IGRAPH statt diagrammer eine Option ist - vielleicht ist das nicht der Fall ...

Wir verlassen Positionierung der Eckpunkte zu einem Standard-Layout-Algorithmus und Abfrage es für die daraus entstehenden Eckpunktpositionen . Diese Positionen werden dann verwendet, um ein gepunktetes Rechteck um eine beliebige Menge von "ausgewählten" Ecken zu zeichnen. Es ist keine Benutzerinteraktion erforderlich.

Wir beginnen mit der Diagrammtopologie.

library(igraph) 

set.seed(42) 

df <- data.frame(from = c('A', 'B', 'I', 'D', 'D', 'E', 'E', 'F', 'F', 'G'), 
       to = c('B', 'C', 'I', 'E', 'F', 'G', 'F', 'H', 'G', 'H')) 

g <- graph.data.frame(df, directed = TRUE) 

Die Größe der Scheitelpunkte und Pfeile in der Grafik kann frei eingestellt werden, je nach Geschmack.

vertexsize <- 50 
arrowsize <- 0.2 

Wir bitten die Fruchterman-Reingold-Layout-Engine, die Koordinaten der Scheitelpunkte zu berechnen.

coords <- layout_with_fr(g) 

Dann plotten Sie die Grafik.

plot(g, 
    layout = coords, 
    vertex.size = vertexsize, 
    edge.arrow.size = arrowsize, 
    rescale = FALSE, 
    xlim = range(coords[,1]), 
    ylim = range(coords[,2])) 

Wenn wir sehen wollen, was los ist, können wir Achsen hinzufügen koordinieren und den Scheitelpunkt drucken Koordinaten:

axis(1) 
axis(2) 

V(g) # ordered vertex list 
coords # coordinates of the vertices (in the same coordinate system as our dotted rectangle) 

Wir haben jetzt den Begrenzungsrahmen der Eckpunkte herausfinden, dass wir ein Rechteck um wollen .

selectedVertices = c("A", "B", "C") 
vertexIndices <- sapply(selectedVertices, FUN = function(x) { return(as.numeric(V(g)[x])) }) 
llx <- min(coords[vertexIndices, 1]) 
lly <- min(coords[vertexIndices, 2]) 
urx <- max(coords[vertexIndices, 1]) 
ury <- max(coords[vertexIndices, 2]) 

Fast da.Wir haben bereits die Koordinaten der Ecke Zentren in coords [], aber wir brauchen auch die Größe der Vertices im Koordinatensystem von plot(). Aus dem Quelltext von plot.igraph können wir sehen, dass die Option vertex.size für plot() durch 200 geteilt und dann als Radius zum Zeichnen des Scheitelpunkts verwendet wird. Wir verwenden einen um 50% größeren Wert als den Rand um die Begrenzungsbox der Vertex-Koordinaten, wenn das gepunktete Rechteck gezeichnet wird.

margin <- (vertexsize/200) * 1.5 
rect(llx - margin, lly - margin, urx + margin, ury + margin, lty = 'dotted') 

Dies ist das Ergebnis erhalten wir:

enter image description here

5

Sie könnten die @ StevenBeaupre-Lösung für das Widget verwenden, aber es gibt ein paar Pakete zum Zeichnen von Netzwerken mit R-Grafiken. Einer ist igraph, wenn Sie für andere Lösungen offen sind.

Dies wird die grafische Darstellung

library('igraph') 
set.seed(11) 
g <- data.frame(from = c('A', 'B', 'I', 'D', 'D', 'E', 'E', 'F', 'F', 'G'), 
       to = c('B', 'C', 'I', 'E', 'F', 'G', 'F', 'H', 'G', 'H')) 
(gg <- graph.data.frame(g, directed = TRUE)) 
plot(gg, vertex.color = 'white') 

Und es gibt viele Möglichkeiten, machen eine Box r Grafiken hinzuzufügen; hier ist eine, wo man den Plot klicken kann, um das Feld zu addieren, ohne etwas

rekt <- function(...) { 
    coords <- c(unlist(locator(1)), unlist(locator(1))) 
    rect(coords[1], coords[2], coords[3], coords[4], ..., xpd = NA) 
} 

rekt(border = 'red', lty = 'dotted', lwd = 2) 

ich diese

bekommen berechnen zu müssen ist

enter image description here

+0

Gibt es eine Möglichkeit, dies reproduzierbar zu machen, d. H. Das manuelle Klicken entfällt? – histelheim

+0

@histelheim Ich kann mir keinen schönen Weg vorstellen. 'igraph' hat einige eingebaute Layouts'? iigraph :: layout', die bestimmen, wo alles statt zufällig ist. Sie könnten eine Matrix für das Layout angeben, so dass Sie die Koordinaten im Voraus kennen – rawr

+0

Ich kann angeben, wo die Knoten gehen, ich kann einfach nicht angeben, wo das Rechteck geht ... – histelheim

2

Eine einfache Lösung mit DiagrammR Punkt eher wäre als neato zu verwenden. Meist verlieren Sie die Fähigkeit, die Knoten manuell zu positionieren (Attribut pos funktioniert nicht mehr), aber Sie können Cluster und Subgraph verwenden, um Linien um Knotengruppen zu zeichnen.

library(DiagrammeR) 
grViz(" 
     digraph boxes_and_circles { 

     # a 'graph' statement 
     graph [ fontsize = 10,rankdir=LR] 

     # several 'node' statements 
     node [shape = circle, 
     fontname = Helvetica] 

     # several 'edge' statements 

     subgraph cluster_1 { 
      style=dotted 
      A->B->C 
     } 

     D->E D->F E->F E->G F->G G->H F->H 
     I 
     } 

     ") 

enter image description here

+0

Wenn Sie das 'fdp'-Layout verwenden, können Sie' pos' verwenden - aber die Positionen sind lokal für den Cluster (i tihnk). Sie können die Positionen wahrscheinlich anpassen, indem Sie unsichtbare Knoten/Kanten hinzufügen. – user20650