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

新手求助:如何用D3.js从CSV提取Score列并绘制折线图?

解决D3.js CSV导入与指定列折线图绘制问题

核心实现步骤

  • 处理D3.js异步加载CSV的特性
  • 筛选出Date及所有Score类列(如Value A(score)、Value B(score))
  • 构建适配折线图的数据集并完成绘制

完整代码实现

// 设置SVG画布的基础尺寸与边距
const margin = { top: 20, right: 80, bottom: 30, left: 50 };
const width = 800 - margin.left - margin.right;
const height = 500 - margin.top - margin.bottom;

// 创建SVG容器
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})`);

// 异步加载CSV文件(D3 v5+基于Promise,必须在回调内处理数据)
d3.csv("your-data-file.csv").then(rawData => {
  // 1. 提取目标列:Date + 所有带"(score)"的列
  const scoreColumns = Object.keys(rawData[0]).filter(col => col.includes("(score)"));
  const targetColumns = ["Date", ...scoreColumns];

  // 2. 转换数据格式,构建dataset
  // 整理为多折线需要的系列结构:每个系列包含名称与对应的数据点
  const dataset = scoreColumns.map(col => {
    return {
      seriesName: col.replace("(score)", "").trim(), // 简化系列名称
      values: rawData.map(row => {
        return {
          date: d3.timeParse("%Y-%m-%d")(row.Date), // 根据你的日期格式调整解析规则
          score: +row[col] // 将分数字符串转为数值类型
        };
      })
    };
  });

  // 3. 定义坐标轴比例尺
  const xScale = d3.scaleTime()
    .domain(d3.extent(rawData, d => d3.timeParse("%Y-%m-%d")(d.Date)))
    .range([0, width]);

  const yScale = d3.scaleLinear()
    .domain([0, d3.max(dataset, d => d3.max(d.values, v => v.score))])
    .range([height, 0]);

  // 4. 创建折线生成器
  const lineGenerator = d3.line()
    .x(d => xScale(d.date))
    .y(d => yScale(d.score))
    .curve(d3.curveMonotoneX); // 生成平滑折线

  // 5. 绘制多条折线
  const colorScale = d3.scaleOrdinal(d3.schemeCategory10); // 用不同颜色区分系列

  svg.selectAll(".line")
    .data(dataset)
    .enter()
    .append("path")
    .attr("class", "line")
    .attr("d", d => lineGenerator(d.values))
    .attr("stroke", (d, i) => colorScale(i))
    .attr("stroke-width", 2)
    .attr("fill", "none");

  // 6. 绘制坐标轴
  svg.append("g")
    .attr("transform", `translate(0, ${height})`)
    .call(d3.axisBottom(xScale));

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

  // 7. 添加图例(可选,方便区分不同折线)
  const legend = svg.selectAll(".legend")
    .data(dataset)
    .enter()
    .append("g")
    .attr("class", "legend")
    .attr("transform", (d, i) => `translate(${width + 10}, ${i * 20})`);

  legend.append("rect")
    .attr("width", 15)
    .attr("height", 15)
    .attr("fill", (d, i) => colorScale(i));

  legend.append("text")
    .attr("x", 20)
    .attr("y", 12)
    .text(d => d.seriesName);
}).catch(error => {
  console.error("CSV加载失败:", error);
});

关键细节说明

  • 异步处理:d3.csv()返回Promise,必须在.then()回调内操作数据,否则会因异步加载未完成导致数据未定义。
  • 列筛选逻辑:通过Object.keys(rawData[0])获取CSV所有列名,再用filter()匹配带"(score)"的列,结合Date列得到目标字段。
  • 数据格式转换:将原始行数据转为多折线所需的系列结构,同时解析日期字符串为Date对象、转换分数为数值,确保比例尺能正确识别数据类型。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 06:40:47