2016-02-08 6 views
8

Das networkD3-Paket (siehe here und here) ermöglicht es dem Benutzer einfache interaktive Netzwerke zu erstellen:R networkD3 Paket: Knoten Färbung in simpleNetwork()

# Load package 
library(networkD3) 

# Create fake data 
src <- c("A", "A", "A", "A", 
     "B", "B", "C", "C", "D") 
target <- c("B", "C", "D", "J", 
      "E", "F", "G", "H", "I") 
networkData <- data.frame(src, target) 

# Plot 
simpleNetwork(networkData) 

Gibt es eine Möglichkeit zu geben, dass ich alle Elemente wollen in der src Vektor eine bestimmte Farbe zu sein, während alle Elemente in der target Vektor eine andere Farbe zu sein? Dies würde es mir ermöglichen, src Knoten von target Knoten im Netzwerk visuell zu unterscheiden.

Diese Funktionalität scheint derzeit nicht in simpleNetwork() unterstützt werden (aber ich bin der Hoffnung, jemand mich mit einem Homebrew-Skript helfen könnte):

enter image description here

Eine ähnliche, aber nicht im Zusammenhang Frage asked here wurde .

+1

Ist es ok, forceNetwork() ', im selben Paket zu verwenden? Sie können die Farbe über die Gruppe und eine JavaScript-Skala steuern. Ich kann eine vollständige Antwort geben, wenn Sie daran interessiert sind. –

+0

@PeterEllis Ja, das wäre sehr hilfreich. – warship

+0

möglicherweise eine verwandte Frage, wobei man die Knoten mit vordefinierten Farben färben muss: http://stackoverflow.com/questions/38793947/r-colouring-scheme-in-networkd3-vs-igraph?noredirect=1#comment65115769_38793947 –

Antwort

7

Hier ist, wie mit forceNetwork Farbe von Knoten zu steuern. Beachten Sie, dass Ihnen die Richtung der Links immer noch nicht bekannt ist, da einige Knoten die Quelle für einige Links und das Ziel für andere sind - Sie müssen diese Logik also irgendwie überdenken. Wie auch immer, hier wird die Farbe der Knoten kontrolliert.

# Load package 
library(networkD3) 
library(dplyr) # to make the joins easier 

# Create fake data 
src <- c("A", "A", "A", "A", 
     "B", "B", "C", "C", "D") 
target <- c("B", "C", "D", "J", 
      "E", "F", "G", "H", "I") 
networkData <- data.frame(src, target, stringsAsFactors = FALSE) 

nodes <- data.frame(name = unique(c(src, target)), stringsAsFactors = FALSE) 
nodes$id <- 0:(nrow(nodes) - 1) 


# create a data frame of the edges that uses id 0:9 instead of their names 
edges <- networkData %>% 
    left_join(nodes, by = c("src" = "name")) %>% 
    select(-src) %>% 
    rename(source = id) %>% 
    left_join(nodes, by = c("target" = "name")) %>% 
    select(-target) %>% 
    rename(target = id) 

edges$width <- 1 

# make a grouping variable that will match to colours 
nodes$group <- ifelse(nodes$name %in% src, "lions", "tigers") 

# simple with default colours 
forceNetwork(Links = edges, Nodes = nodes, 
      Source = "source", 
      Target = "target", 
      NodeID ="name", 
      Group = "group", 
      Value = "width", 
      opacity = 0.9, 
      zoom = TRUE) 

# control colours with a JS ordinal scale 
# edited 20 May 2017 with updated code from Renal Chesak's answer: 
ColourScale <- 'd3.scaleOrdinal() 
      .domain(["lions", "tigers"]) 
      .range(["#FF6900", "#694489"]);' 

forceNetwork(Links = edges, Nodes = nodes, 
      Source = "source", 
      Target = "target", 
      NodeID ="name", 
      Group = "group", 
      Value = "width", 
      opacity = 0.9, 
      zoom = TRUE, 
      colourScale = JS(ColourScale)) 

enter image description here

+2

Es wäre schön, die Knoten alle beschriftet zu haben. Könnten Sie bitte Ihre Antwort erweitern, um zu zeigen, wie die Namen der Knoten (sowohl für "src" als auch für "target") automatisch angezeigt werden und nicht nur für die Hover-Barrierefreiheit? – warship

+0

Dafür gibt es ein Argument namens "opacityNoHover". Verwenden Sie 'opacityNoHover = 1', um die Knotenbeschriftungen immer anzuzeigen. –

1

Sie könnten eine ähnliche Sache wie im verknüpften Beitrag tun, aber hier ist ein Beispiel mit dem visNetwork Paket. Dieses Paket verbindet sich mit vis.js und macht wirklich nette interaktive Graphen.

library(visNetwork) 
id <- unique(c(src, target))         # node ids 
nodes <- data.frame(id, group=+(id %in% src),     # add a grouping for src/target 
    label=id, title=sprintf('<p>Node %s</p>', id))    # add some labels 
g <- visNetwork(nodes=nodes, edges=networkData, width="75%") # make graph 
visExport(visHierarchicalLayout(g))       # make it tree-like 

enter image description here

+0

Sehr cool . Ich hoffe, Sie finden etwas ähnliches in 'networkD3' :-) +1 – warship

4

Peter Ellis Antwort oben auf einmal gearbeitet haben könnte, aber es scheint, den Code in einer neuen Version aktualisiert. Statt d3.scale.ordinal().range([]), müssen Sie verwenden d3.scaleOrdinal().range([])

+2

Danke. Ich benutze diese Kombination nicht sehr oft und habe die Veränderung erst drei Jahre nach deiner Antwort gesehen, als ich mich in meiner eigenen Arbeit gefragt habe, warum das nicht mehr funktioniert! Ich habe meine ursprüngliche Antwort als Antwort bearbeitet. –

1

Peter Ellis Antwort macht den Job, aber das ist ein alternativer Ansatz, der imho ist etwas kürzer und einfacher zu verstehen ...

library(networkD3) 

src <- c("A", "A", "A", "A", "B", "B", "C", "C", "D") 
target <- c("B", "C", "D", "J", "E", "F", "G", "H", "I") 
networkData <- data.frame(src, target, stringsAsFactors = FALSE) 

# make a nodes data frame out of all unique nodes in networkData 
nodes <- data.frame(name = unique(c(networkData$src, networkData$target))) 

# make a group variable where nodes in networkData$src are identified 
nodes$group <- nodes$name %in% networkData$src 

# make a links data frame using the indexes (0-based) of nodes in 'nodes' 
links <- data.frame(source = match(networkData$src, nodes$name) - 1, 
        target = match(networkData$target, nodes$name) - 1) 

forceNetwork(Links = links, Nodes = nodes, Source = "source", 
      Target = "target", NodeID ="name", Group = "group", 
      opacity = 1, opacityNoHover = 1)