Place nodes explicitly with visNetwork (or an Alternative)

876 Views Asked by At

How can I explicitly place nodes on a visNetwork graph?

Or: How can I recreate that graphic in R using visNetwork or an alternative?

enter image description here

Background: The ultimate goal is to represent Causal Loop Diagrams coming from Vensim files. Placing the nodes explicitly is just the first (crucial) step, because in Causal Loop Diagrams the visual mapping of nodes is part of the information (unlike in general graph theory). So if anybody has advice on the bigger picture aka. 'Bringing Causal Loop Diagram Modeling to R', I'll be more than happy.

What I tried:

library("visNetwork")

nodes <- data.frame(id = 1:3, label = c("one", "two", "three"))
edges <- data.frame(from = c(1,1,2), to = c(2,3,1))

visNetwork(nodes, edges, width = "100%", title = nodes$labels, stringsAsFactors = FALSE) %>% visEdges(arrows = "to")

which plots something like (exact layout will change, because of random seed):

enter image description here

With the Q&A from here I tried to place nodes manually by setting x and y values.

library("visNetwork")

nodes <- data.frame(id = 1:3, label = c("one", "two", "three"), x = c(0,1,2), y = c(0,1,2))
edges <- data.frame(from = c(1,1,2), to = c(2,3,1))

visNetwork(nodes, edges, width = "100%", title = nodes$labels, stringsAsFactors = FALSE) %>% visEdges(arrows = "to")

which plots:

enter image description here

..and I really don't understand what's the correspondance between x, y and the placing on the screen..

Also I could not find anything in the docs for visLayout.

2

There are 2 best solutions below

1
On BEST ANSWER

Using ggraph instead of visNetwork simplifies things.

library(ggraph)
library(igraph)

g <- make_graph(edges = c(1,2,2,1,1,3))
V(g)$name <- c('one', 'two', 'three')

ggraph(g, layout = 'manual', node.positions = data.frame(x = c(1,1,2), y = c(2,1,2.1))) + 
  geom_edge_arc(aes(start_cap = label_rect(node1.name),
                    end_cap = label_rect(node2.name)),
                 angle_calc = 'along',
                 label_dodge = unit(2.5, 'mm'),
                 arrow = arrow(length = unit(4, 'mm'))) + 
  geom_node_text(aes(label = name, x = x, y = y))

This plotsenter image description here

which is (apart from gridlines and colours) what I was searching for.

2
On

It somehow turns out, that the x and y args are not working. Here a solution:

library("visNetwork")

nodes <- data.frame(id = 1:3, label = c("one", "two", "three"))
edges <- data.frame(from = c(1,1,2), to = c(2,3,1))

coords <- as.matrix(data.frame(x = c(0,1,2),
                               y = c(0,1,2),
                               stringsAsFactors = FALSE))

visNetwork(nodes, edges, width = "100%", title = nodes$labels) %>%
    visNodes() %>%
    visOptions(highlightNearest = TRUE) %>%
    visInteraction(navigationButtons = TRUE,
                   dragNodes = TRUE, dragView = TRUE,
                   zoomView = FALSE) %>%
    visEdges(arrows = 'to') %>%
    visIgraphLayout(layout = "layout.norm", layoutMatrix = coords)

For history see also here. Perhaps these links might be helpful for what you want to achive: causaleffect and plot.CLD