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

如何使用D3.js基于指定CSV数据绘制分组条形图 解决A/B/C类别拆分问题

D3.js 长格式数据绘制分组条形图解决方案

你之前参考的教程适配的是宽格式CSV(每一行对应一个大分组,每一列存储一个类别的数值),而你当前使用的是长格式CSV,所以需要先调整数据处理逻辑,具体实现步骤如下:

1. 预定义配色映射

按照需求配置tipology和颜色的对应规则:

const colorMap = d3.scaleOrdinal()
  .domain(["A", "B", "C"])
  .range(["red", "blue", "green"]);

2. 数据读取与预处理

读取CSV后先做格式转换、缺失值补全,保证每个大分组下都有A、B、C三类的完整数据:

d3.csv("你的数据文件路径.csv").then(rawData => {
  // 将value字段转换为数值类型
  rawData.forEach(item => item.value = Number(item.value));

  // 提取所有大分组、所有类别枚举值
  const allGroups = [...new Set(rawData.map(item => item.group))];
  const allTipologies = ["A", "B", "C"];

  // 补全每个大分组下的三类数据,缺失值填充为0,避免分组缺类
  const formattedData = allGroups.map(groupName => {
    const groupItems = rawData.filter(item => item.group === groupName);
    const fullItems = allTipologies.map(tip => {
      const matched = groupItems.find(item => item.tipology === tip);
      return {
        group: groupName,
        tipology: tip,
        value: matched ? matched.value : 0
      }
    });
    return [groupName, fullItems];
  });

  // 后续比例尺配置、绘图逻辑都在这个回调内执行
})

3. 双X轴比例尺配置

分组条形图需要两层X轴比例尺:外层控制大分组的位置,内层控制每个大分组内三类条形的偏移:

// 画布尺寸可根据需求调整
const width = 600, height = 400, margin = {top: 20, right: 20, bottom: 30, left: 40};

// 外层X比例尺:映射大分组位置
const xGroupScale = d3.scaleBand()
  .domain(allGroups)
  .range([margin.left, width - margin.right])
  .padding(0.2);

// 内层X比例尺:映射大分组内三类条形的位置
const xTipScale = d3.scaleBand()
  .domain(allTipologies)
  .range([0, xGroupScale.bandwidth()])
  .padding(0.05);

// Y比例尺:映射数值高度
const yScale = d3.scaleLinear()
  .domain([0, d3.max(rawData, item => item.value)])
  .range([height - margin.bottom, margin.top]);

4. 绘制条形元素

先为每个大分组创建容器,再在容器内绘制对应三类的条形:

const svg = d3.select("你的svg选择器")
  .attr("width", width)
  .attr("height", height);

// 绘制大分组容器
const groupContainers = svg.selectAll("g.group-container")
  .data(formattedData)
  .join("g")
  .attr("transform", d => `translate(${xGroupScale(d[0])}, 0)`);

// 绘制每个类别条形
groupContainers.selectAll("rect.tip-bar")
  .data(d => d[1])
  .join("rect")
  .attr("class", "tip-bar")
  .attr("x", d => xTipScale(d.tipology))
  .attr("y", d => yScale(d.value))
  .attr("width", xTipScale.bandwidth())
  .attr("height", d => height - margin.bottom - yScale(d.value))
  .attr("fill", d => colorMap(d.tipology));

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 19:45:07