D3.js散点图无显示问题求助:附多变量数据集与代码
问题排查与修复方案
核心错误点
- 重复创建SVG+宽高初始化错误:页面已存在
<svg>元素,代码中又append("svg")创建新SVG,且新SVG未设置初始宽高,导致parseInt(svg.attr('width'))返回NaN,后续所有尺寸设置全部失效。 - 轴容器创建错误:
d3.append("g")是直接向文档根节点添加元素,而非添加到目标SVG中,正确写法应为svg.append("g")。 - Scale与Axis绑定逻辑错误:D3中需先独立创建比例尺函数,再将其绑定到轴组件,而非直接在
<g>元素上链式调用比例尺方法。 - 脚本标签语法错误:引入D3的
<script>标签未闭合,导致后续自定义代码无法被浏览器解析执行。 - X轴Domain处理不当:直接用
data.map(d => d.year)会生成大量重复年份值,ScaleBand要求Domain是唯一值集合。
修正后的核心代码示例
<!DOCTYPE html> <html lang="en"> <body> <!-- 保留页面初始SVG,不再重复创建 --> <svg width="1000" height="1000"></svg> <!-- 先闭合引入D3的script标签,再开启新标签编写自定义代码 --> <script src="https://d3js.org/d3.v4.js" charset="utf-8"></script> <script> var margin = {top:100, right:80, bottom:80, left:80}; // 选择页面已有的SVG元素 var svg = d3.select("svg"); // 获取初始宽高并计算带边距的总尺寸 var width = parseInt(svg.attr('width')); var height = parseInt(svg.attr("height")); svg.attr("width", width + margin.left + margin.right); svg.attr("height", height + margin.top + margin.bottom); // 加载数据并处理 d3.csv("data/programmingassignment1data.csv", function(error, data){ if (error) throw error; data.forEach(function(d){ d.year = +d.year; d.percentile = +d.percentile; d.avg_welfare = +d.avg_welfare; d.pop_share = +d.pop_share; d.welfare_share = +d.welfare_share; }); // 1. 创建X轴比例尺(提取去重年份作为Domain) var xScale = d3.scaleBand() .domain(d3.map(data, d => d.year).keys()) .range([margin.left, width - margin.right]) .padding(0.4); // 2. 创建X轴容器并绑定比例尺 var xAxis = svg.append("g") .attr("transform", `translate(0, ${height - margin.bottom})`) .call(d3.axisBottom(xScale)); // 3. 以avg_welfare为例创建Y轴比例尺与轴容器 var yScaleAvg = d3.scaleLinear() .domain([0, d3.max(data, d => d.avg_welfare)]) .range([height - margin.bottom, margin.top]); var yAxisAvg = svg.append("g") .attr("transform", `translate(${margin.left}, 0)`) .call(d3.axisLeft(yScaleAvg)); // 4. 绘制avg_welfare对应的散点 svg.selectAll(".avg-point") .data(data) .enter() .append("circle") .attr("class", "avg-point") .attr("cx", d => xScale(d.year)) .attr("cy", d => yScaleAvg(d.avg_welfare)) .attr("r", 3) .attr("fill", "steelblue"); // 可重复上述Y轴+散点逻辑,实现welfare_share、pop_share的区域展示 }); </script> </body> </html>
额外说明
- 针对Y轴三个区域的需求,需分别为
avg_welfare、welfare_share、pop_share创建独立的Y轴比例尺,将每个变量的散点映射到对应的Y轴范围。 - 若要在X轴同时展示年份与百分位数,可将
year+'-'+percentile作为组合值传入ScaleBand的Domain,或采用分组轴的方式实现层级展示。
内容的提问来源于stack exchange,提问作者Esther
相关产品推荐
相关产品推荐

