在SAS EG中用JavaScript+D3 3.x生成桑基图遇空白输出求助
在SAS EG中生成D3桑基图的完整解决方案
我明白你在SAS EG里尝试用PROC STREAM/TEMPLATE生成D3桑基图却得到空白页面的困扰——大概率是数据传递环节没处理好,或者桑基图需要的nodes+links格式没正确生成。下面是一步到位的解决方案,直接用你提供的测试数据生成可用的桑基图:
步骤1:准备SAS数据集
先把你的输入数据转换成SAS数据集,方便后续处理:
/* 创建桑基图的链接数据 */ data sankey_links; length source $1 target $1; input source $ target $ value; datalines; A X 5 A Y 7 A Z 6 B X 2 B Y 9 B Z 4 X L 5 ; run;
步骤2:将SAS数据转为JSON格式
桑基图需要JSON格式的数据,我们用PROC JSON生成JSON字符串并存储到宏变量中:
/* 临时存储JSON文件 */ filename json_temp temp; /* 导出SAS数据集为JSON,保留原始字段名 */ proc json out=json_temp nosastags pretty; export sankey_links / keysource=source keytarget=target keyvalue=value; run; /* 将JSON内容读入宏变量,方便嵌入HTML */ data _null_; infile json_temp lrecl=32767 truncover; length json_str $32767; retain json_str ''; input line $char32767.; json_str = catx('', json_str, line); /* 转义双引号,避免HTML里的语法冲突 */ json_str = tranwrd(json_str, '"', '\\"'); call symputx('sankey_json', json_str); run; filename json_temp clear;
步骤3:用PROC STREAM生成包含D3代码的HTML
这里我们直接把D3 v3的CDN引用、桑基图代码和嵌入的JSON数据整合到HTML中,重点修改了原代码的数据源部分(不再异步加载外部JSON,而是直接使用SAS传递的链接数据,并自动生成节点列表):
/* 生成最终的HTML文件,可指定输出路径 */ filename sankey_html "&your_output_path./sankey_diagram.html"; proc stream out=sankey_html; begin <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>SAS D3 Sankey Diagram</title> <!-- 引用D3.js v3版本(桑基图依赖v3的API) --> <script src="https://d3js.org/d3.v3.min.js"></script> <style> .link { fill: none; stroke: #000; stroke-opacity: .2; } .link:hover { stroke-opacity: .5; } .node rect { cursor: move; fill-opacity: .9; shape-rendering: crispEdges; } .node text { pointer-events: none; text-shadow: 0 1px 0 #fff; } </style> </head> <body> <script> // 从SAS传递过来的链接数据 var links = &sankey_json.; // 自动生成桑基图需要的节点列表(去重所有source/target) var nodes = {}; links.forEach(function(link) { link.source = nodes[link.source] || (nodes[link.source] = {name: link.source}); link.target = nodes[link.target] || (nodes[link.target] = {name: link.target}); link.value = +link.value; }); // 组装桑基图需要的标准格式:nodes + links var graph = { nodes: d3.values(nodes), links: links }; // 桑基图核心配置(和原代码一致) var width = 960, height = 500; var color = d3.scale.category20(); var sankey = d3.sankey() .nodeWidth(15) .nodePadding(10) .size([width, height]); var path = sankey.link(); var svg = d3.select("body").append("svg") .attr("width", width) .attr("height", height) .append("g") .attr("transform", "translate(0,0)"); sankey .nodes(graph.nodes) .links(graph.links) .layout(32); // 绘制链接 var link = svg.append("g").selectAll(".link") .data(graph.links) .enter().append("path") .attr("class", "link") .attr("d", path) .style("stroke-width", function(d) { return Math.max(1, d.dy); }) .sort(function(a, b) { return b.dy - a.dy; }); link.append("title") .text(function(d) { return d.source.name + " → " + d.target.name + "\n" + d.value; }); // 绘制节点 var node = svg.append("g").selectAll(".node") .data(graph.nodes) .enter().append("g") .attr("class", "node") .attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; }) .call(d3.behavior.drag() .origin(function(d) { return d; }) .on("dragstart", function() { this.parentNode.appendChild(this); }) .on("drag", dragmove)); node.append("rect") .attr("height", function(d) { return d.dy; }) .attr("width", sankey.nodeWidth()) .style("fill", function(d) { return d.color = color(d.name.replace(/ .*/, "")); }) .style("stroke", function(d) { return d3.rgb(d.color).darker(2); }) .append("title") .text(function(d) { return d.name + "\n" + d.value; }); node.append("text") .attr("x", -6) .attr("y", function(d) { return d.dy / 2; }) .attr("dy", ".35em") .attr("text-anchor", "end") .attr("transform", null) .text(function(d) { return d.name; }) .filter(function(d) { return d.x < width / 2; }) .attr("x", 6 + sankey.nodeWidth()) .attr("text-anchor", "start"); // 节点拖拽功能 function dragmove(d) { d3.select(this).attr("transform", "translate(" + d.x + "," + (d.y = Math.max(0, Math.min(height - d.dy, d3.event.y))) + ")"); sankey.relayout(); link.attr("d", path); } </script> </body> </html> ; end; run; filename sankey_html clear;
关键注意事项(解决空白问题的核心)
- D3版本匹配:原代码用的是D3 v3,必须引用
d3.v3.min.js,不能用v4+版本(API完全不兼容)。 - 数据格式转换:桑基图需要
nodes(节点列表)和links(链接列表)两个部分,你提供的原始数据只有links,必须通过JS代码自动提取节点并生成nodes数组。 - 宏变量转义:SAS宏变量里的双引号要转义成
\",否则会破坏HTML/JS的语法结构,导致代码无法执行。 - 路径权限:确保你指定的
&your_output_path.是SAS EG有读写权限的路径,比如你的个人目录或者服务器共享目录。
运行完这段代码后,找到生成的HTML文件,用浏览器打开就能看到和你期望的同款桑基图了!
内容的提问来源于stack exchange,提问作者user7078484
相关产品推荐
相关产品推荐

