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

如何用D3.js基于特定CSV及嵌套后JSON绘制折线图

How to Plot a Line Chart with D3.js Using Your Nested CSV Data

Got it, let's walk through exactly how to turn that nested data structure into a clean line chart. The key issue here is converting that single-object-in-an-array format into the array of (x,y) points that D3's line generator expects. Here's a step-by-step breakdown with code:

1. First, Transform Your Nested Data

Right now, each entry in your nested array looks like this:

{ key: "type1", values: [{"1": "54.69801915", "2": "84.4717406", ..., "48": "xxx"}] }

We need to convert that single object inside values into an array of points where each point has an x (the 1-48 index) and y (the numeric value). Add this transformation step right after your d3.nest() call:

// Assume your nested data is stored in `nestedData`
const readyData = nestedData.map(d => {
  // Extract the single object from values array
  const valueObj = d.values[0];
  // Convert object entries to (x,y) points
  const points = Object.entries(valueObj).map(([xStr, yStr]) => ({
    x: parseInt(xStr), // Convert "1" string to numeric 1
    y: Number(yStr)    // Convert string value to numeric
  }));
  // Return a cleaned object with type and point array
  return {
    type: d.key,
    points: points
  };
});

This gives you an array where each item has a type label and a points array of properly formatted (x,y) pairs—perfect for D3's line generator.

2. Set Up Your SVG & Scales

Next, create your SVG canvas and define scales for the x and y axes. We'll use linear scales since both your x (1-48) and y (numeric values) are continuous:

// Set up margins to avoid cutting off axes/lines
const margin = { top: 20, right: 30, bottom: 30, left: 40 };
const width = 800 - margin.left - margin.right;
const height = 500 - margin.top - margin.bottom;

// Create SVG container with inner group for margins
const svg = d3.select("body")
  .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})`);

// Calculate global min/max for y-axis (fits all lines in the chart)
const allYValues = readyData.flatMap(d => d.points.map(p => p.y));
const yMin = d3.min(allYValues);
const yMax = d3.max(allYValues);

// Define scales
const xScale = d3.scaleLinear()
  .domain([1, 48]) // X values range from 1 to 48
  .range([0, width]);

const yScale = d3.scaleLinear()
  .domain([yMin - 5, yMax + 5]) // Add padding to avoid cutting off line edges
  .range([height, 0]); // D3 uses top-down y, so reverse range for correct orientation

// Add axes
svg.append("g")
  .attr("transform", `translate(0, ${height})`)
  .call(d3.axisBottom(xScale));

svg.append("g")
  .call(d3.axisLeft(yScale));

3. Create the Line Generator & Draw Lines

Now define a D3 line generator that knows how to access the x and y values from your points, then loop through your readyData to draw each line:

// Define line generator (add curve for smoothness if desired)
const line = d3.line()
  .x(d => xScale(d.x))
  .y(d => yScale(d.y))
  .curve(d3.curveMonotoneX); // Optional: removes sharp angles, use curveLinear for straight lines

// Draw each line
svg.selectAll(".line")
  .data(readyData)
  .enter()
  .append("path")
  .attr("class", "line")
  .attr("d", d => line(d.points))
  .style("stroke", (d, i) => d3.schemeCategory10[i]) // Use D3's built-in color scheme
  .style("stroke-width", 2)
  .style("fill", "none");

// Optional: Add a legend to identify each line
const legend = svg.append("g")
  .attr("transform", `translate(${width - 100}, 10)`);

legend.selectAll(".legend-item")
  .data(readyData)
  .enter()
  .append("g")
  .attr("class", "legend-item")
  .attr("transform", (d, i) => `translate(0, ${i * 20})`)
  .each(function(d, i) {
    d3.select(this)
      .append("rect")
      .attr("width", 15)
      .attr("height", 15)
      .style("fill", d3.schemeCategory10[i]);
    
    d3.select(this)
      .append("text")
      .attr("x", 20)
      .attr("y", 12)
      .text(d.type)
      .style("font-size", "12px");
  });

Key Notes to Remember

  • Data Type Conversion: Always convert CSV string values to numbers—D3 can't plot strings correctly.
  • Global Axis Domain: Calculating the overall y min/max ensures all lines fit within the chart, instead of scaling each line independently.
  • Line Customization: Swap out curveMonotoneX for other curve types (like curveStep or curveNatural) to change line styling, or adjust stroke colors/widths to match your design.

That's it! This will generate a fully functional line chart with one line per type from your original CSV data.

内容的提问来源于stack exchange,提问作者Thusitha Thilina Dayaratne

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 10:02:38