2

I am currently working with the R forceNetwork function of the networkD3 package and I have properly validated the correctness of the Nodes and Links data frames for my graph.

My Nodes data frame (node_df) is like this:

   node_id  node_type node_size
0  T054717 irrelevant        10
1  T095006 irrelevant        10
2  T088658 irrelevant        10
3  T069179 irrelevant        10
4  T009515 irrelevant        10
5  T152167 irrelevant        10
6  T100447 irrelevant        10
7  T150659 irrelevant        10
...

and My Links dataframe (links_df) is like this:

    tid1 tid2 edge_dir
0     37   36       10
1     37    0       10
2     37    1       10
3     37    3       10
...
147   34   35        5
148    7   47        5
149   34   47        5
150   35   47        5
151   36   48        5
152    1   48        5

I set the forceNetwork function like this:

network <- forceNetwork (Links = links_df,
                           Nodes = node_df,
                           Source = "tid1",
                           Target = "tid2",
                           Value = "edge_dir",
                           NodeID = "node_id",
                           Nodesize = "node_size",
                           Group = "node_type",
                           colourScale = JS("d3.scaleOrdinal(d3.schemeCategory20);"),
                           fontSize = 10,
                           linkDistance = 100,
                           radiusCalculation = JS(" Math.sqrt(d.nodesize)+6"), 
                           charge = -30,
                           linkColour = ifelse(links_df$edge_dir == 10, "black","red"),
                           opacity = 1,
                           zoom = TRUE,
                           arrows = ifelse(links_df$edge_dir == 10, TRUE, FALSE),
                           opacityNoHover = TRUE,
                           clickAction = NULL)

I am struggling with the arrows parameter of the function. In fact I would like to specify if there should be a directed edge (arrows = TRUE) or an undirected edge (arrows = FALSE) for each link, by checking the Value parameter.

In my case Value refers to a column of the Links data frame named edge_dir, which specifies if the edge should be directed (edge_dir = 10) or not (edge_dir = 5).

After looking at this stackoverflow link, specify-colors-for-each-link-in-a-force-directed-network-networkd3

I've tried to set the parameter like this: arrows = ifelse(links_df$edge_dir == 10, TRUE, FALSE) but the output graph has arrows where there just should be undirected lines.

Using the same structure in the linkColour parameter: linkColour = ifelse(links_df$edge_dir == 10, "black","red") it works fine, directed edges are black and the ones that should be undirected, but they aren't, are red, as shown in this graph output image

Is it possible to display a graph which has directed and undirected edges by modifying the arrows parameter? Thank you!

  • Since you have not offered any data, you should instead make your attempts using the example on the page you linked to. It has an accepted answer and allows us to look at the results. We cannot see what happens with your data since we are not sitting at your elbow. (There are no arrows in the output from the example from the accepted answer.) – IRTFM Nov 03 '21 at 15:15
  • I followed your suggestion @IRTFM and I tried the accepted answer code for the forceNetwork function [https://stackoverflow.com/a/39782310/6304083] and I added `arrows = ifelse(MisLinks$value > 1, TRUE, FALSE)`. Every edge of the output graph has a arrow now, even if the ones with value<1 shouldn't. I don't understand what is wrong with the code line for arrows I've customized – Camilla9347 Nov 03 '21 at 16:40
  • The `arrows` parameter is just a flag to enable arrows to be displayed. It's not a per-link vector. I think you should be modifying your Value parameter. I think this is a duplicate to https://stackoverflow.com/questions/51024363/forcenetwork-networkd3-arrow-issue BTW, I do thank you for this question even if it is a duplicate because I had not seen this structure before and it looks fascinationg. – IRTFM Nov 03 '21 at 17:46
  • 1
    Does this answer your question? [forceNetwork networkD3 - Arrow issue](https://stackoverflow.com/questions/51024363/forcenetwork-networkd3-arrow-issue) – Dylan_Gomes Nov 03 '21 at 18:54
  • The `arrow` parameter is all or nothing. To get turn on or off arrows per link, you would have to modify the underlying JavaScript. – CJ Yetman Nov 03 '21 at 20:23
  • @IRTFM, I have looked into the link you and Dylan_Gomes suggested and I think I got the *Value* parameter ok, since in my graph it is called *edge_dir* and it is numeric and associated to the links data frame correctly. Thank you! – Camilla9347 Nov 04 '21 at 09:48
  • @CJYetman After many tries and fails I've realized you were right and I think I misread the R forceNetwork() documentation. I don't know how to access the underlying JavaScript or even if I could be able to make a useful modification. So I will search for an alternative in order to visualize a CPDAG in a similar interactive way. Thank you! – Camilla9347 Nov 04 '21 at 09:52

1 Answers1

1

This is an imperfect solution, but it's easier than making substantial modifications to the underlying JavaScript yourself. You can use htmlwidgets::onRender() to inject some JavaScript to run just after the plot is generated. Here's an example of how you could turn off the arrows for only those links that have a value equal to 5...

library(tibble)
library(networkD3)
library(htmlwidgets)

node_df <- tibble::tribble(
  ~node_id,  ~node_type,   ~node_size, ~directed,
  "T054717", "irrelevant", 10,       TRUE,
  "T095006", "irrelevant", 10,       FALSE,
  "T088658", "irrelevant", 10,       TRUE,
  "T069179", "irrelevant", 10,       FALSE,
  "T009515", "irrelevant", 10,       TRUE,
  "T152167", "irrelevant", 10,       FALSE,
  "T100447", "irrelevant", 10,       TRUE,
  "T150659", "irrelevant", 10,       FALSE
  )

links_df <- tibble::tribble(
  ~tid1, ~tid2, ~edge_dir,
  0,     1,     10,
  0,     2,     10,
  0,     3,     10,
  1,     3,     10,
  2,     4,     5,
  2,     5,     5,
  3,     6,     5,
  4,     5,     5,
  5,     6,     5,
  5,     6,     5
  )

network <- forceNetwork (Links = links_df,
                         Nodes = node_df,
                         Source = "tid1",
                         Target = "tid2",
                         Value = "edge_dir",
                         NodeID = "node_id",
                         Nodesize = "node_size",
                         Group = "node_type",
                         colourScale = JS("d3.scaleOrdinal(d3.schemeCategory20);"),
                         fontSize = 10,
                         linkDistance = 100,
                         radiusCalculation = JS(" Math.sqrt(d.nodesize)+6"),
                         charge = -30,
                         linkColour = ifelse(links_df$edge_dir == 10, "black","red"),
                         opacity = 1,
                         zoom = TRUE,
                         arrows = ifelse(links_df$edge_dir == 10, TRUE, FALSE),
                         opacityNoHover = TRUE,
                         clickAction = NULL)

htmlwidgets::onRender(network, '
  function(el) {
    d3.select("svg")
      .selectAll(".link")
      .filter(function(d) { return d.value == 5; })
      .style("marker-end", null);
  }')

enter image description here

CJ Yetman
  • 8,373
  • 2
  • 24
  • 56