You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用D3.js读取CSV生成直方图时遇Uncaught TypeError错误求助

Fixing "Uncaught TypeError: Cannot read property 'dx' of undefined" in D3 Histogram

Let's break down why you're hitting this error and how to fix it step by step:

Root Cause

The error happens because data[0] is undefined—meaning the histogram data array generated by d3.layout.histogram() is empty. This stems from two key issues in your code:

  1. Incorrect CSV data parsing: d3.csv returns an array of row objects, but you're using Object.keys(data).map(...) which maps over array indices instead of actual data rows.
  2. Missing type conversion: CSV values are read as strings by default. If you don't convert them to numbers, d3.layout.histogram() can't generate valid bins, resulting in an empty data array.

Step-by-Step Fixes

1. Correctly Parse and Clean CSV Data

Replace your values assignment with this code to properly convert and filter data:

values = data.map(function(row) {
  // Convert string value to number; mark invalid entries as null
  const num = +row['Calculus I'];
  return isNaN(num) ? null : num;
}).filter(val => val !== null); // Remove null/invalid values

This directly maps over each CSV row, converts the "Calculus I" value to a number, and filters out any entries that can't be converted.

2. Replace data[0].dx with a Reliable Width Calculation

Instead of relying on data[0] (which fails if data is empty), calculate each bar's width using its own bin values:

.attr("width", function(d) {
  return x(d.x + d.dx) - x(d.x) - 1; // Subtract 1 for small spacing between bars
})

This works for every bin individually, no need to reference the first element.

3. Add a Guard Clause for Empty Data

Prevent crashes when there's no valid data by adding a check before generating the histogram:

if (values.length === 0) {
  console.error("No valid numeric data found in CSV");
  return;
}

Full Modified Code

Here's the complete corrected code with all fixes applied:

var values = [];
d3.csv('../static/CSV/Chart_data/histogram_sub.csv?rnd='+(new Date).getTime(), function(data) {
  // Parse and clean CSV data
  values = data.map(function(row) {
    const num = +row['Calculus I'];
    return isNaN(num) ? null : num;
  }).filter(val => val !== null);

  // Guard against empty data
  if (values.length === 0) {
    console.error("No valid numeric data to generate histogram");
    return;
  }

  var color = "steelblue";
  var formatCount = d3.format(",.0f");

  var margin = {top: 20, right: 30, bottom: 30, left: 30},
      width = 800 - margin.left - margin.right,
      height = 400 - margin.top - margin.bottom;

  var max = d3.max(values);
  var min = d3.min(values);

  var x = d3.scale.linear()
      .domain([min, max])
      .range([0, width]);

  // Generate histogram bins (renamed to histData to avoid confusion)
  var histData = d3.layout.histogram()
      .bins(x.ticks(20))
      (values);

  var yMax = d3.max(histData, function(d){return d.length});
  var yMin = d3.min(histData, function(d){return d.length});

  var colorScale = d3.scale.linear()
      .domain([yMin, yMax])
      .range([d3.rgb(color).brighter(), d3.rgb(color).darker()]);

  var y = d3.scale.linear()
      .domain([0, yMax])
      .range([height, 0]);

  var xAxis = d3.svg.axis()
      .scale(x)
      .orient("bottom");

  var svg = d3.select("#Histogram2").append("svg")
      .attr("width", width + margin.left + margin.right)
      .attr("height", height + margin.top + margin.bottom)
      .append("g")
      .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

  var bar = svg.selectAll(".bar")
      .data(histData)
      .enter().append("g")
      .attr("class", "bar")
      .attr("transform", function(d) { return "translate(" + x(d.x) + "," + y(d.y) + ")"; });

  bar.append("rect")
      .attr("x", 1)
      .attr("width", function(d) { return x(d.x + d.dx) - x(d.x) - 1; })
      .attr("height", function(d) { return height - y(d.y); })
      .attr("fill", function(d) { return colorScale(d.y); });

  bar.append("text")
      .attr("dy", ".75em")
      .attr("y", -12)
      .attr("x", function(d) { return (x(d.x + d.dx) - x(d.x)) / 2; })
      .attr("text-anchor", "middle")
      .text(function(d) { return formatCount(d.y); });

  svg.append("g")
      .attr("class", "x axis")
      .attr("transform", "translate(0," + height + ")")
      .call(xAxis);
});

Key Notes

  • I renamed the histogram data variable to histData to avoid confusion with the original CSV data variable, making the code easier to read.
  • The +row['Calculus I'] conversion is critical—without it, your values are strings, and D3's histogram function can't create meaningful bins.
  • The guard clause ensures your code doesn't attempt to render a histogram when there's no valid data, preventing further errors.

内容的提问来源于stack exchange,提问作者MTT

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 06:40:08