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

D3水平条形图堆叠与过滤异常问题求助

D3水平条形图问题排查与修复

问题现象

  • 仅需展示前5行数据的水平条形图,但5条数据被合并为单个条形,未形成独立的5个条形
  • 条形方向错误:预期水平排列,实际呈现垂直排列
  • 已过滤的数据仍出现在图表中

错误的图表效果

用户提供的原代码

// define the dimensions and margins for the graph
var margin = {top:20, right:20, bottom:100, left:80},
  width = 1960 - margin.left - margin.right,
  height = 500 - margin.top - margin.bottom


// append svg element to the body of the page
var svg = d3.select("body").append("svg")
    // set the id, dimensions and position of the svg element
  .attr("id","svg1")
  .attr("width", width + margin.left + margin.right)
  .attr("height", height + margin.top + margin.bottom)
  .append('g')
  .attr("id","container")
  .attr("transform", "translate(" + margin.left + "," +margin.top +")");
var bars = svg.append("g")
  .attr("id", "bars");

// Get the data
var pathToCsv = "example.csv";   // path to csv
d3.dsv(",", pathToCsv, function (d) {
  return {
    species: d.species,
    count: +d.count
  }
}).then(function (data) {
  console.log(data);
  /* Create bar plot using data from csv */
  
data = data.filter(function(d,i){return i<5});

  // create scales x & y for X and Y axis and set their ranges
var x = d3.scaleLinear().domain([0,d3.max(data, function(d) { return d.count})]).range([0,width])
var y = d3.scaleBand().domain(d3.map((e,i) => i)).range([height,0])


  // Add bars to svg - create new elements based on your data
  bars.selectAll(".bar")
    .data(data)
    .enter().append("rect")
    .attr("class","bar")
    .attr("x", function(d) {
      return x(d.count);
    })
    .attr("y", function (d){
      var v = data.species
      return y(v);
    })
    .attr("width", function (d) {
      return x(d.count)
    })
    .attr("height", 10);

问题根源

  1. Y轴比例尺配置错误:
    • 用d3.map((e,i) => i)生成定义域的写法无效,未与数据的唯一标识(如species)绑定
    • 计算Y轴位置时错误调用data.species(这是数组的不存在属性),导致所有条形Y坐标一致,重叠成一个
  2. 条形位置逻辑错误:
    • 水平条形图的x属性应从0开始,原代码用x(d.count)导致条形从数值位置反向绘制,呈现垂直效果
    • 固定高度10未利用scaleBand的自适应带宽,无法合理分配垂直空间
  3. 数据过滤冗余:filter取前5条的写法可行,但用slice(0,5)更简洁且不易出错

修复后的代码

// define the dimensions and margins for the graph
var margin = {top:20, right:20, bottom:100, left:80},
    width = 1960 - margin.left - margin.right,
    height = 500 - margin.top - margin.bottom

// append svg element to the body of the page
var svg = d3.select("body").append("svg")
    .attr("id","svg1")
    .attr("width", width + margin.left + margin.right)
    .attr("height", height + margin.top + margin.bottom)
    .append('g')
    .attr("id","container")
    .attr("transform", "translate(" + margin.left + "," +margin.top +")");
var bars = svg.append("g")
    .attr("id", "bars");

// Get the data
var pathToCsv = "example.csv";   // path to csv
d3.dsv(",", pathToCsv, function (d) {
    return {
        species: d.species,
        count: +d.count
    }
}).then(function (data) {
    console.log(data);
    // 取前5条数据,slice写法更简洁
    data = data.slice(0,5);

    // 创建比例尺:x轴对应count数值,y轴对应每个species
    var x = d3.scaleLinear()
        .domain([0, d3.max(data, function(d) { return d.count; })])
        .range([0, width]);
    
    // Y轴用species作为定义域,添加padding避免条形重叠
    var y = d3.scaleBand()
        .domain(data.map(function(d) { return d.species; }))
        .range([0, height])
        .padding(0.1);

    // 添加条形
    bars.selectAll(".bar")
        .data(data)
        .enter().append("rect")
        .attr("class","bar")
        // 水平条形从x=0位置开始绘制
        .attr("x", 0)
        // Y轴位置绑定当前数据的species
        .attr("y", function (d){
            return y(d.species);
        })
        // 宽度对应count的数值
        .attr("width", function (d) {
            return x(d.count);
        })
        // 高度使用scaleBand的自适应带宽
        .attr("height", y.bandwidth());
});

关键修复点

  • 用slice(0,5)替代filter,简洁获取前5条数据
  • Y轴比例尺绑定数据的species字段,确保每个条形有独立的垂直位置
  • 水平条形的x属性设为0,保证从左侧起始绘制
  • 条形高度使用y.bandwidth(),配合padding实现自适应垂直空间分配

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.11 15:05:05