networkD3 icon indicating copy to clipboard operation
networkD3 copied to clipboard

bug in rendering forceNetwork when arrows = TRUE and Value = NULL

Open Whil- opened this issue 6 years ago • 8 comments

Hi!

I'm trying to create a simple network graph with directed arrows and I only get a strange result back.

Code attached, and resulting graph is shown here: image

library(networkD3)
source <- c(0,0,1,1)
target <- c(1,2,2,3)
name <- c('zero','one','two','three')
group <- c('Group 1','Group 1','Group 2','Group 2')

links <- data.frame(source,target)
nodes <- data.frame(name,group)

forceNetwork(Links = links, Nodes = nodes, 
             Source = "source", Target = "target", 
             NodeID = "name", Group = "group", 
             linkDistance = 100, zoom = TRUE,
             fontSize = 14, opacity = 0.8, legend = T, arrows = T)

version 0.4 downloaded using install.packages("networkD3") in RStudio.

Whil- avatar Aug 24 '17 19:08 Whil-

Thanks for the reproducible example! I can confirm this behavior on 0.4 and dev. It will take a while to figure this out. Strange behavior considering the following works as expected...

library(networkD3)

URL <- paste0("https://cdn.rawgit.com/christophergandrud/networkD3/",
              "master/JSONdata/miserables.json")
MisJson <- jsonlite::fromJSON(URL)

forceNetwork(Links = MisJson$links[1:10, ], Nodes = MisJson$nodes[1:10, ], 
             Source = "source", Target = "target", Value = "value", 
             NodeID = "name", Group = "group", arrows = TRUE)

cjyetman avatar Aug 25 '17 09:08 cjyetman

This easily can be worked around by adding a value column to the links df, and setting the Value parameter of forceNetwork() to the name of that column. For instance...

library(networkD3)
source <- c(0,0,1,1)
target <- c(1,2,2,3)
name <- c('zero','one','two','three')
group <- c('Group 1','Group 1','Group 2','Group 2')

links <- data.frame(source,target,value = 1L) # add value to links df
nodes <- data.frame(name,group)

forceNetwork(Links = links, Nodes = nodes,
             Source = "source", Target = "target",
             NodeID = "name", Group = "group", 
             Value = "value", arrows = T) # set Value to name of value column in links df

This still exposes a legitimate issue though. forceNetwork() prepares the data to pass through to htmlwidgets::createWidget, and passes through a df with no value column if none was specified (lines 193-195). If a value column is necessary for the JavaScript to work properly, maybe it should create a sane default (e.g. value = 1L) if no value column is specified. That would be an easy fix, but I have to consider what side effects that might have. Alternatively, the JavaScript should / could be modified to function properly even when there is no value column in the data... that would be a bit more challenging to review and fix.

cjyetman avatar Aug 26 '17 14:08 cjyetman

The simple solution seems reasonable.

christophergandrud avatar Aug 27 '17 05:08 christophergandrud

Thanks a lot, with your input it works again. For me this issue is closed. If you want to keep it open longer I'll leave it as is.

Regards

Whil- avatar Aug 28 '17 22:08 Whil-

Leave it open. Eventually we’ll make this tiny fix.

cjyetman avatar Aug 29 '17 01:08 cjyetman

Hi, I have this issue as well even when specifying "Value" as suggested. I tried both version 0.4 and the latest development version.

ms5505 avatar Apr 15 '18 02:04 ms5505

Please provide a minimal reproducible example.

cjyetman avatar Apr 15 '18 05:04 cjyetman

The work-around failed for me even after specifying Value when I still provided a linkWidth argument (minimal reproducible example below). It was solved when I removed the linkWidth argument. I'm using networkD3 0.4, but did not test in dev.

library(networkD3)
source <- c(0,0,0,1,1)
target <- c(0,1,2,2,3)
name <- c('zero','one','two','three')
group <- c('Group 1','Group 1','Group 1','Group 1')

links <- data.frame(source,target,value = 1L) # add value to links df
nodes <- data.frame(name,group)

forceNetwork(Links = links, Nodes = nodes,
             Source = "source", Target = "target",
             NodeID = "name", Group = "group", 
             Value = "value", 
             linkWidth = 1L, 
             arrows = T) 
# comment out linkWidth = 1L to get correct plot

sprouffske avatar Jul 19 '19 09:07 sprouffske