I would like to produce a Sankey-diagram using the networkD3 package in R that has the functionality as described in this question, and the "highlight_node_links" function in the answer:
d3 Sankey - Highlight all connected paths from start to end
I'm a beginner with both R and Javascript and my problem is that I cannot make the above javascript function work with my R code. I have checked Highlight all connected paths from start to end in Sankey graph using R question too, but unfortunately I couldn't solve it based on the answer there either. I do understand I need to use htmlwidgets::onRender
, but cannot figure out how.
A small sample data and the network generated from it:
links = data.frame(source = c("me", "you", "she", "p1", "p1", "p2", "p2"), target = c("p1", "p2", "p1", "p2", "b1", "b1", "b2"), weight = c(20, 10, 30, 40, 60, 50, 50))
nodes <- data.frame(name = c(links$source, links$target) %>% unique())
links$IDsource = match(links$source, nodes$name)-1
links$IDtarget = match(links$target, nodes$name)-1
sn <- sankeyNetwork(Links = links,
Nodes = nodes,
Source = "IDsource",
Target = "IDtarget",
Value = "weight",
NodeID = "name",
sinksRight = TRUE)
And the way I tried to include the highlight_node_links
function (that I defined earlier unchanged from the above link):
htmlwidgets::onRender(
sn,
'
function(el, x) {
var link = d3.selectAll(".link");
var node = d3.selectAll(".node");
node.on("mousedown.drag", null);
node.on("click",highlight_node_links);
function highlight_node_links(node,i){
var remainingNodes=[],
nextNodes=[];
var stroke_opacity = 0;
if( d3.select(this).attr("data-clicked") == "1" ){
d3.select(this).attr("data-clicked","0");
stroke_opacity = 0.2;
}else{
d3.select(this).attr("data-clicked","1");
stroke_opacity = 0.5;
}
var traverse = [{
linkType : "sourceLinks",
nodeType : "target"
},{
linkType : "targetLinks",
nodeType : "source"
}];
traverse.forEach(function(step){
node[step.linkType].forEach(function(link) {
remainingNodes.push(link[step.nodeType]);
highlight_link(link.id, stroke_opacity);
});
while (remainingNodes.length) {
nextNodes = [];
remainingNodes.forEach(function(node) {
node[step.linkType].forEach(function(link) {
nextNodes.push(link[step.nodeType]);
highlight_link(link.id, stroke_opacity);
});
});
remainingNodes = nextNodes;
}
});
}
function highlight_link(id,opacity){
d3.select("#link-"+id).style("stroke-opacity", opacity)
}}'
)
答案 0 :(得分:1)
运行代码时,我收到警告消息...
Warning message:
It looks like Source/Target is not zero-indexed. This is required in JavaScript
and so your plot may not render.
告诉您问题的根源是... links
和nodes
数据帧未正确创建。
您可以通过在创建stringsAsFactors = FALSE
数据框的data.frame
命令中添加links
作为参数来轻松解决此问题。
工作示例...
library(networkD3)
library(htmlwidgets)
library(dplyr)
links = data.frame(
source = c("me", "you", "she", "p1", "p1", "p2", "p2"),
target = c("p1", "p2", "p1", "p2", "b1", "b1", "b2"),
weight = c(20, 10, 30, 40, 60, 50, 50),
stringsAsFactors = FALSE
)
nodes <-
data.frame(name = c(links$source, links$target) %>% unique())
links$IDsource = match(links$source, nodes$name) - 1
links$IDtarget = match(links$target, nodes$name) - 1
sn <- sankeyNetwork(
Links = links,
Nodes = nodes,
Source = "IDsource",
Target = "IDtarget",
Value = "weight",
NodeID = "name",
sinksRight = TRUE
)
htmlwidgets::onRender(
sn,
'
function(el, x) {
var link = d3.selectAll(".link");
var node = d3.selectAll(".node");
node.on("mousedown.drag", null);
node.on("click",highlight_node_links)}'
)