如何在R的sankeyNetwork中添加(log10)P值连线宽度图例?
给networkD3桑基图添加连线宽度图例
可以通过扩展onRender中的JavaScript代码,直接在桑基图的SVG容器里绘制自定义的宽度图例。以下是修改后的完整代码,已集成图例绘制逻辑:
library(networkD3) library(htmlwidgets) library(webshot) # 读取数据(保留原有逻辑) data <- read.csv("sankeydata.csv") path <- unique(as.character(data$to)) nodes <- data.frame(node = c(0:43), name = c(path, "T0", "F_T24", "F_T72", "F_T96", "P_T24", "P_T48")) links <- data[ , c("node.x", "node.y", "logpvalue")] colnames(links) <- c("source", "target", "logpvalue") # 创建桑基图(调整右侧边距预留图例空间) sn <- sankeyNetwork(Links = links, Nodes = nodes, Source = "target", Target = "source", Value = "logpvalue", NodeID = "name", fontFamily = "Arial", fontSize= 12, nodeWidth = 20, margin = list(left = 260, right = 150)) # 扩展JS逻辑:调整文本对齐 + 添加宽度图例 sankey <- onRender( sn, ' function(el, x) { // 原有文本对齐调整 d3.selectAll(".node text").attr("text-anchor", "begin").attr("x", 21); // 绘制连线宽度图例 var svg = d3.select(el).select("svg"); var margin = {right: 100, top: 20}; var legendWidth = 120; var legendHeight = 150; // 创建图例容器,放置在右上角 var legend = svg.append("g") .attr("transform", "translate(" + (svg.attr("width") - margin.right - legendWidth) + "," + margin.top + ")"); // 获取logpvalue的范围,选取关键刻度(可按需修改) var values = x.links.map(d => d.logpvalue); var minVal = d3.min(values); var maxVal = d3.max(values); var midVal = (minVal + maxVal) / 2; var legendVals = [minVal, midVal, maxVal]; // 匹配桑基图的宽度缩放逻辑 var widthScale = d3.scaleLinear() .domain([0, maxVal]) .range([1, 20]); // 对应桑基图连线的最小/最大宽度,可根据实际效果调整 // 绘制图例线条和文本标签 legendVals.forEach((val, i) => { var y = i * 40; // 绘制对应宽度的线条 legend.append("line") .attr("x1", 0) .attr("x2", legendWidth - 40) .attr("y1", y + 5) .attr("y2", y + 5) .attr("stroke", "#ccc") .attr("stroke-width", widthScale(val)); // 绘制数值标签 legend.append("text") .attr("x", legendWidth - 30) .attr("y", y + 10) .attr("font-size", "10px") .attr("font-family", "Arial") .text(val.toFixed(1)); // 保留1位小数,按需调整 }); // 添加图例标题 legend.append("text") .attr("x", 0) .attr("y", -5) .attr("font-size", "12px") .attr("font-weight", "bold") .attr("font-family", "Arial") .text("log10(P值)"); } ' ) # 显示桑基图 sankey # 保存为图片(需先保存完整HTML再截图) saveWidget(sankey, "sankey.html") webshot("sankey.html", "sankeySO.png")
关键调整说明:
- 给
sankeyNetwork增加了右侧边距,避免图例与桑基图主体重叠 - 在JS逻辑中:
- 提取所有连线的
logpvalue值,计算出最小、中间、最大值作为图例刻度 - 用线性比例尺匹配桑基图的连线宽度缩放规则,保证图例宽度与实际连线一致
- 在SVG右上角绘制不同宽度的参考线和对应数值,添加图例标题
- 提取所有连线的
- 优化了图片保存流程,确保包含图例的完整内容被截图
你可以根据实际的logpvalue分布,修改legendVals里的刻度值,或者调整widthScale的范围参数,让图例和桑基图的匹配度更高。
内容的提问来源于stack exchange,提问作者Larissa Carvalho
相关产品推荐
相关产品推荐

