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

如何在D3.js v5中基于嵌套数据为分组条形图指定定义域

分组条形图定义域设置方案(D3.js v5 + 可选Lodash)

嘿,针对你用D3.js v5构建分组条形图的定义域需求,结合你提供的groupeddata数据,我整理了一套实用的实现步骤,不管用D3原生方法还是Lodash都能搞定:

1. 先提取核心的唯一数据

分组条形图需要两个关键的定义域维度:分组名称(Title)和组内的子类别(ID),另外Y轴需要基于RFU的数值范围。首先得从原始数据里把不重复的分组和子类别捞出来:

用D3原生方法提取

// 获取所有不重复的分组名称
const groupNames = d3.map(groupeddata, d => d.Title).keys();
// 获取所有不重复的子类别ID
const subgroupNames = d3.map(groupeddata, d => d.ID).keys();

用Lodash简化操作(如果你引入了Lodash)

// 一键提取唯一Title
const groupNames = _.uniq(_.map(groupeddata, 'Title'));
// 一键提取唯一ID
const subgroupNames = _.uniq(_.map(groupeddata, 'ID'));

2. 对原始数据做分组处理

为了后续方便绑定数据绘制条形,我们需要把原始数据按Title分组,每个分组下包含对应ID的RFU数据:

D3 v5的分组方式(注意v5用d3.nest,v6+才是d3.group)

const groupedData = d3.nest()
  .key(d => d.Title)
  .entries(groupeddata);
// 输出结构大概是:[{key: "Dummy Data", values: [...]}, {key: "Dummy Data2", values: [...]}]

Lodash的分组方式更简洁

const groupedData = _.groupBy(groupeddata, 'Title');
// 输出结构:{"Dummy Data": [...], "Dummy Data2": [...]}

3. 设置比例尺的定义域

接下来就是核心的比例尺配置了,分组条形图需要两个X轴比例尺(外层分组、内层子类别)和一个Y轴数值比例尺:

X轴双比例尺配置

// 外层X比例尺:对应分组名称,控制分组之间的位置
const xGroupScale = d3.scaleBand()
  .domain(groupNames) // 定义域就是我们提取的唯一分组名
  .range([0, width]) // width是你预先设定的图表宽度
  .padding(0.2); // 分组之间的间距,数值越大间距越宽

// 内层X比例尺:对应每个分组下的子类别,控制组内条形的位置
const xSubgroupScale = d3.scaleBand()
  .domain(subgroupNames) // 定义域是唯一的子类别ID
  .range([0, xGroupScale.bandwidth()]) // 用外层分组的宽度作为内层比例尺的范围
  .padding(0.1); // 组内条形之间的间距

Y轴数值比例尺配置

// 先找到所有RFU值里的最大值,作为Y轴的上限
const maxRFU = d3.max(groupeddata, d => d.RFU);

const yScale = d3.scaleLinear()
  .domain([0, maxRFU]) // Y轴从0到最大RFU值
  .range([height, 0]); // height是图表高度,注意D3的Y轴是从上到下数值递增,所以range是[height, 0]

4. 绑定数据绘制条形

最后一步就是把数据绑定到DOM元素上绘制条形了:

// 先添加分组容器,每个分组对应一个<g>标签
const groupContainers = svg.selectAll('.bar-group')
  .data(groupedData)
  .enter()
  .append('g')
  .attr('class', 'bar-group')
  .attr('transform', d => `translate(${xGroupScale(d.key || Object.keys(groupedData).find(k => groupedData[k] === d))}, 0)`); 
  // 注:D3 nest结果用d.key,Lodash分组结果需要匹配对应的分组键名

// 在每个分组容器里绘制条形
groupContainers.selectAll('rect')
  .data(d => d.values) // 每个分组下的子数据
  .enter()
  .append('rect')
  .attr('x', d => xSubgroupScale(d.ID)) // 组内条形的X位置
  .attr('y', d => yScale(d.RFU)) // 条形顶部的Y位置
  .attr('width', xSubgroupScale.bandwidth()) // 条形宽度
  .attr('height', d => height - yScale(d.RFU)) // 条形高度(从Y轴位置到图表底部)
  .attr('fill', d => d.barcolor); // 用数据里的barcolor设置条形颜色

这样就能完美实现分组条形图的定义域配置和基础绘制啦,要是想调整间距或者样式,直接修改比例尺的padding参数就行~

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 09:34:21