当我点击节点以了解特定节点的整个故事时,我想强调整个路径,这是一个示例 - http://bl.ocks.org/git-ashish/8959771。
请检查此链接,你会发现在javscript中突出显示路径的功能,但请注意,此功能不能做我想要的,它突出显示与被点击的节点相关的链接以及与目标相关的链接节点。我想要的是突出显示与点击的节点相关的所有链接。
d3 Sankey - Highlight all connected paths from start to end
这是我需要的一个例子, 这是整个图表,我需要的是,当我点击曼谷时,它会突出显示与数据框中曼谷相同的所有节点,例如突出显示与ClimateChange和EnergyShortage的链接,然后突出显示基础设施&生态系统,领导力和战略,...... 这就是我想要的。 这是另一张图片,显示与曼谷相关的节点使用闪亮来分析它。
当我在bl.ocks和链接的问题中使用highlight_node_links时会发生什么,这是错误的,并且没有显示节点和曼谷之间的关系。
以下是曼谷的数据,向您展示列如何相互关联,以及当您使用此数据时,它将仅生成第二张图片。
structure(list(City = c("Bangkok", "Bangkok", "Bangkok", "Bangkok",
"Bangkok", "Bangkok", "Bangkok", "Bangkok", "Bangkok", "Bangkok",
"Bangkok", "Bangkok", "Bangkok", "Bangkok", "Bangkok", "Bangkok"
), ResiliencyChallenge = c("ClimateChange", "ClimateChange",
"ClimateChange", "ClimateChange", "ClimateChange", "InfrastructureFaliure",
"EnergyShortage", "Pollution", "Pollution", "Pollution", "TransportationSystemFailure",
"TransportationSystemFailure", "TransportationSystemFailure",
"TransportationSystemFailure", "TransportationSystemFailure",
"TransportationSystemFailure"), CRI.Dimesnsion.1 = c("Infrastructure & Ecosystems",
"Infrastructure & Ecosystems", "Infrastructure & Ecosystems",
"Infrastructure & Ecosystems", "Infrastructure & Ecosystems",
"Infrastructure & Ecosystems", "Infrastructure & Ecosystems",
"Leadership & Strategy", "Leadership & Strategy", "Infrastructure & Ecosystems",
"Infrastructure & Ecosystems", "Infrastructure & Ecosystems",
"Infrastructure & Ecosystems", "Infrastructure & Ecosystems",
"Infrastructure & Ecosystems", "Leadership & Strategy"), Implementation.time.frame = c("Short-term",
"Short-term", "Short-term", "Short-term", "Short-term", "Mid-term",
"Long-term", "Short-term", "Short-term", "Mid-term", "Mid-term",
"Short-term", "Short-term", "Short-term", "Short-term", "Short-term"
), Goal = c("Goal13", "Goal13", "Goal13", "Goal13", "Goal13",
"Goal12", "Goal12", "Goal11", "Goal11", "Goal11", "Goal11", "Goal11",
"Goal11", "Goal11", "Goal11", "Goal11")), .Names = c("City",
"ResiliencyChallenge", "CRI.Dimesnsion.1", "Implementation.time.frame",
"Goal"), class = "data.frame", row.names = c(NA, -16L))
答案 0 :(得分:1)
鉴于您提供的R代码数据结构......
首先,sankeyNetwork
期望列出边/链接的数据以及通过这些链接连接的节点。您的数据有......让我们称之为“旅行者”中心格式,其中您的每一行数据都与特定的“路径”相关。因此,首先您需要将该数据转换为sankeyNetwork
所需的数据类型,同时保留识别它们来自路径的链接所需的信息。此外,您的数据中只有一个城市,因此除非数据中的路径至少有两个不同的来源,否则很难看到结果,因此我将复制它并将第二组归因于另一个城市。这是一个例子......
library(tidyverse)
# duplicate the data for another city so we have more than 1 origin
links <-
df %>%
full_join(mutate(df, City = "Hong Kong")) %>%
mutate(row = row_number()) %>%
mutate(origin = .[[1]]) %>%
gather("column", "source", -row, -origin) %>%
mutate(column = match(column, names(df))) %>%
arrange(row, column) %>%
group_by(row) %>%
mutate(target = lead(source)) %>%
ungroup() %>%
filter(!is.na(target)) %>%
select(source, target, origin) %>%
group_by(source, target, origin) %>%
summarise(count = n()) %>%
ungroup()
nodes <- data.frame(name = unique(c(links$source, links$target)))
links$source <- match(links$source, nodes$name) - 1
links$target <- match(links$target, nodes$name) - 1
现在,links
期望的表单中有nodes
和sankeyNetwork
数据框,而links
数据框有一个额外的列origin
,确定每个链接在路径上的哪个城市。您现在可以使用sankeyNetwork
绘制此内容,在原始数据中添加,因为它被剥离,然后使用htmlwidgets::onRender
指定一个点击行为,该行为会更改源自城市节点的任何链接的不透明度点击了......
library(networkD3)
library(htmlwidgets)
sn <- sankeyNetwork(Links = links, Nodes = nodes, Source = 'source',
Target = 'target', Value = 'count', NodeID = 'name')
# add origin back into the links data because sankeyNetwork strips it out
sn$x$links$origin <- links$origin
# add onRender JavaScript to set the click behavior
htmlwidgets::onRender(
sn,
'
function(el, x) {
var nodes = d3.selectAll(".node");
var links = d3.selectAll(".link");
nodes.on("mousedown.drag", null); // remove the drag because it conflicts
nodes.on("click", clicked);
function clicked(d, i) {
links
.style("stroke-opacity", function(d1) {
return d1.origin == d.name ? 0.5 : 0.2;
});
}
}
'
)
以上是上述答案的简化版本(使用较小的示例数据集),它将每个“路径”分开,而不是像路径一样聚合并递增计数/值变量。
library(dplyr)
library(tidyr)
library(networkD3)
library(htmlwidgets)
df <- read.csv(header = T, as.is = T, text = '
name,origin,layover,destination
Bob,Baltimore,Chicago,Los Angeles
Bob,Baltimore,Chicago,Seattle
Bob,New York,St Louis,Austin
Bob,New York,Chicago,Seattle
Tom,Baltimore,Chicago,Los Angeles
Tom,New York,St Louis,San Diego
Tom,New York,Chicago,Seattle
Tom,New York,New Orleans,Austin
')
links <-
df %>%
mutate(row = row_number()) %>%
mutate(traveler = .[[1]]) %>%
gather("column", "source", -row, -traveler) %>%
mutate(column = match(column, names(df))) %>%
arrange(row, column) %>%
group_by(row) %>%
mutate(target = lead(source)) %>%
ungroup() %>%
filter(!is.na(target)) %>%
select(source, target, traveler) %>%
group_by(source, target, traveler) %>%
summarise(count = n()) %>%
ungroup()
nodes <- data.frame(name = unique(c(links$source, links$target)))
links$source <- match(links$source, nodes$name) - 1
links$target <- match(links$target, nodes$name) - 1
sn <- sankeyNetwork(Links = links, Nodes = nodes, Source = 'source',
Target = 'target', Value = 'count', NodeID = 'name')
# add origin back into the links data because sankeyNetwork strips it out
sn$x$links$traveler <- links$traveler
# add onRender JavaScript to set the click behavior
htmlwidgets::onRender(
sn,
'
function(el, x) {
var nodes = d3.selectAll(".node");
var links = d3.selectAll(".link");
nodes.select("rect").style("cursor", "pointer");
nodes.on("mousedown.drag", null); // remove the drag because it conflicts
//nodes.on("mouseout", null);
nodes.on("click", clicked);
function clicked(d, i) {
links
.style("stroke-opacity", function(d1) {
return d1.traveler == d.name ? 0.5 : 0.2;
});
}
}
'
)
答案 1 :(得分:1)
这个问题的实现是在这个闪亮的应用程序中。
https://setsna2.shinyapps.io/sankey-shinyforallcities/
我必须从内部修改networkD3
,我通常将其安装并复制到包含闪亮应用程序的目录中,然后将软件包放入R-lib中。
我对sankeyNetwork.js
函数进行了一些修改,以绘制sankey图。
这是目录的图片,它显示了到达sankeyNetwork.js
手动更改位置的目录结构。
请注意,我在此问题中使用和上传的sankeyNetwork.js
的版本是旧的,它是2年前的,所以您可以下载新版本的networkD3
并只需修改我的部分接下来会提到。
我在sankeyNetwork.js
中所做的更改是添加
.on('mouseover', function(node) {
Shiny.onInputChange("node_name", node.name);
})
这意味着如果有人将鼠标悬停在节点上,我将使用Shiny.onInputChange
将节点名称作为“ node_name”变量传输到我的R会话中,那么您可以在线阅读有关此闪亮功能的更多信息。
这里是我曾经知道我的意思的sankeyNetwork.js
。
现在,如果有人将鼠标悬停在节点上,我可以获取该节点的名称并将其发送给R,如果他移开了光标,我将不会得到任何名称,这就是核心思想。
您可以通过单击here
来查看我闪亮的应用程序的代码您可以看到Data0
变量here的一部分,也可以看到here中的Goals
变量。
在R代码中,您会在代码中找到一些注释,例如“供调试使用此代码”或注释,因此,如果您运行这些注释,则在运行闪亮的应用程序之前,您将了解数据的外观,从而充分了解其运行方式。 sankey图读取数据及其外观。
在R代码中,您会找到从sankeyNetwork.js
读取node_name的部分
NodeName <- reactive({
if(length(input$node_name)>0){return(as.character(input$node_name))}
else{return(0)}
})
然后代码中的下一部分是检查NodeName
是否在我的Nodes
数据框中,如果存在,那么我将得到与该节点相关的所有节点,然后会获得将这些节点相互连接的链接ID,请注意,链接ID从0
开始而不是从1
开始,因为javascript从0开始,R从1开始。
现在我们有了用户悬停的NodeName
和与此节点相关的Links
,现在我们可以制作sankey图并将其保存在sn
中,然后我删除了旧的工具提示,然后添加了一个新的提示。
在使用Shiny时使用onRender
修改sankey图,我使用它来使 Highlighting功能在运行Shiny时以及当用户在节点上悬停时修改sankey图,将获取节点的名称,然后获取链接ID,并在现有的sankey图中搜索链接ID,并增加其不透明度。
请注意,如果您运行该应用程序,将会出错,您必须将其上传到Shinyapps.io上进行调试,这就是我检查我的应用程序是否正确运行的方式,也许您可以找到另一个调试方式。