datastorm-open / visNetwork

R package, using vis.js library for network visualization
Other
545 stars 126 forks source link

Enforcing a 1:1 aspect ratio while preserving other properties #311

Open wlandau opened 5 years ago

wlandau commented 5 years ago

First of all, thank you so much for creating and continuing to maintain visNetwork. Your package has had a huge influence on the success of my favorite project and those of my colleagues.

Desired graph

I am trying to produce a left-to-right hierarchical graph with a 1:1 aspect ratio. This will really help solve https://github.com/ropensci/drake/issues/834.

library(tidyverse)
library(visNetwork)
nodes <- tibble(
  id = seq_len(21),
  x = c(0, rep(0.5, 4), rep(1, 16)),
  y = c(0, seq(.2, .8, length.out = 4), seq(0, 1, length.out = 16)),
  label = sample(letters, size = 21)
)
edges <- tibble(
  from = c(rep(1, 4), rep(seq_len(4) + 1, each = 4)),
  to = c(seq_len(4) + 1, seq_len(16) + 5),
  arrows = "to"
)

# Use visNetwork to generate the graph...

Screenshot_20190415_231313

My attempts so far

library(tidyverse)
library(visNetwork)
set.seed(1)

# I want to control the x and y positions of the nodes
# in order to enforce a 1:1 aspect ratio
nodes <- tibble(
  id = seq_len(21),
  x = c(0, rep(0.5, 4), rep(1, 16)),
  y = c(0, seq(.2, .8, length.out = 4), seq(0, 1, length.out = 16)),
  label = sample(letters, size = 21)
)

edges <- tibble(
  from = c(rep(1, 4), rep(seq_len(4) + 1, each = 4)),
  to = c(seq_len(4) + 1, seq_len(16) + 5),
  arrows = "to"
)

# It can be difficult to get the y positions right.
nodes <- mutate(nodes, y = sample(y))

# And so there are lots of edge crossings in the graph.
visNetwork(nodes = nodes, edges = edges) %>%
  visIgraphLayout(physics = FALSE)


# The Sugiyama layout is designed to minimize edge crossings,
# but it forces the direction to be "UD".
visNetwork(nodes = nodes, edges = edges) %>%
  visIgraphLayout(layout = "layout_with_sugiyama", physics = FALSE)


# And with hierarchical layouts, I have not found a way
# to enforce a 1:1 aspect ratio.
nodes$level <- nodes$x
nodes$x <- nodes$y <- NULL
visNetwork(nodes = nodes, edges = edges) %>%
   visHierarchicalLayout(direction = "LR")


# Combinations do not seem to help.
visNetwork(nodes = nodes, edges = edges) %>%
  visIgraphLayout(physics = FALSE) %>%
   visHierarchicalLayout(direction = "LR")


visNetwork(nodes = nodes, edges = edges) %>%
  visIgraphLayout(layout = "layout_with_sugiyama", physics = FALSE) %>%
   visHierarchicalLayout(direction = "LR")

Created on 2019-04-15 by the reprex package (v0.2.1)

wlandau commented 5 years ago

Ah, I think I figured it out. It's a hack, but I think it's usable.

library(tidyverse)
library(visNetwork)
nodes <- tibble(
  id = seq_len(21),
  x = c(0, rep(0.5, 4), rep(1, 16)),
  y = c(0, seq(.2, .8, length.out = 4), seq(0, 1, length.out = 16)),
  label = sample(letters, size = 21)
)
edges <- tibble(
  from = c(rep(1, 4), rep(seq_len(4) + 1, each = 4)),
  to = c(seq_len(4) + 1, seq_len(16) + 5),
  arrows = "to"
)
out <- visNetwork(nodes = nodes, edges = edges) %>%
  visIgraphLayout(layout = "layout_with_sugiyama", physics = FALSE)
tmp <- out$x$nodes$x
out$x$nodes$x <- out$x$nodes$y
out$x$nodes$y <- tmp
out

Created on 2019-04-17 by the reprex package (v0.2.1)

wlandau commented 5 years ago

I am reopening this issue because I am still having trouble with graphs that are not perfectly balanced. The Sugiyama layout has undesirable edge crossings, and the hierarchical layout has a lopsided aspect ratio. Related: https://github.com/ropensci/drake/issues/834#issuecomment-483935070

library(tidyverse)
library(visNetwork)
nodes <- tibble(
  id = seq_len(22),
  x = c(0, rep(0.5, 4), rep(1, 16), 1.5),
  y = c(0, seq(.2, .8, length.out = 4), seq(0, 1, length.out = 16), 0.8),
  label = sample(letters, size = 22)
)
edges <- tibble(
  from = c(rep(1, 4), rep(seq_len(4) + 1, each = 4), 21),
  to = c(seq_len(4) + 1, seq_len(16) + 5, 22),
  arrows = "to"
)
out <- visNetwork(nodes = nodes, edges = edges) %>%
  visIgraphLayout(layout = "layout_with_sugiyama", physics = FALSE)
tmp <- out$x$nodes$x
out$x$nodes$x <- out$x$nodes$y
out$x$nodes$y <- tmp
out

nodes$level <- nodes$x
visNetwork(nodes = nodes, edges = edges) %>%
  visHierarchicalLayout(direction = "LR")

Created on 2019-04-17 by the reprex package (v0.2.1)

wlandau commented 5 years ago

Update: I input the coordinates incorrectly in the first reprex. I just refreshed https://github.com/datastorm-open/visNetwork/issues/311#issuecomment-484230473.