问题
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)
}}'
)
回答1:
When I run your code, I get the warning message...
Warning message:
It looks like Source/Target is not zero-indexed. This is required in JavaScript
and so your plot may not render.
which tells you what the root of the problem is... your links
and nodes
data frames are not properly created.
You can easily resolve this by adding stringsAsFactors = FALSE
as a parameter to the data.frame
command that you use to create the links
data frame.
Working example...
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)}'
)
来源:https://stackoverflow.com/questions/53850226/highlight-all-connected-paths-from-start-to-end-of-a-sankey-diagram-using-networ