如何对堆积条形图进行数据映射和过滤

How to do data mapping and filter for Stacked Bar graph

本文关键字:数据 映射 过滤 条形图      更新时间:2023-09-26

我在d3.js中实现了堆叠条形图。它适用于多年来城市中各种类别(人群(的人口。虽然在一些参考的帮助下,我取得了一些成果,但我没有得到我想要的确切结果。

我想我在数据映射和过滤器函数中遇到了一些问题,并在色域中分配它们。

任何帮助将不胜感激。

这是我的代码:-

<!DOCTYPE html>
<meta charset="utf-8">
<style>
body {
font: 10px sans-serif;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.bar {
fill: steelblue;
}
.x.axis path {
display: none;
}
</style>
<body>
<script src="http://d3js.org/d3.v3.min.js">
</script>
<script>

var margin = {
  top: 20, right: 20, bottom: 30, left: 40}
    ,
    width = 960 - margin.left - margin.right,
    height = 500 - margin.top - margin.bottom,
    yAxMin_PA = 0,
yAxMax_PA = 1500;
var x = d3.scale.ordinal()
    .rangeRoundBands([0, width], .1);
var  y = d3.scale.linear()
   .domain([yAxMin_PA, yAxMax_PA])
   .range([height, 0]);
var color = d3.scale.category20();
var xAxis = d3.svg.axis()
    .scale(x)
    .orient("bottom");
var yAxis = d3.svg.axis()
    .scale(y)
    .orient("left")
    .tickFormat(d3.format(".2s"));
var 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 + ")");
var data = {
  "bars": [
    {
      "year": 2004,
      "population": [
        {
          "category": 1,
          "strength": 31
        }
        ,
        {
          "category": 2,
          "strength": 21
        }
        ,
        {
          "category": 3,
          "strength": 41
        }
      ]
    }
    ,
    {
      "year": 2005,
      "population": [
        {
          "category": 1,
          "strength": 23
        }
        ,
        {
          "category": 2,
          "strength": 43
        }
        ,
        {
          "category": 3,
          "strength": 33
        }
      ]
    }
    ,
    {
      "year": 2006,
      "population": [
        {
          "category": 1,
          "strength": 29
        }
        ,
        {
          "category": 2,
          "strength": 41
        }
        ,
        {
          "category": 3,
          "strength": 55
        }
        ,
        {
          "category": 4,
          "strength": 69
        }
        ,
        {
          "category": 5,
          "strength": 89
        }
        ,
        {
          "category": 6,
          "strength": 75
        }
      ]
    }
    ,
    {
      "year": 2007,
      "population": [
        {
          "category": 1,
          "strength": 49
        }
        ,
        {
          "category": 2,
          "strength": 43
        }
        ,
        {
          "category": 3,
          "strength": 25
        }
      ]
    }
    ,
    {
      "year": 2008,
      "population": [
        {
          "category": 1,
          "strength": 20 
        }
        ,
        {
          "category": 2,
          "strength": 43
        }
        ,
        {
          "category": 3,
          "strength": 55
        }
      ]
    }
  ]
}
    ;

x.domain(data.bars.map(function(d) {
  return d.year;
}
                      ));
svg.append("g")
  .attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Population");
for (k = 0; k < data.bars.length; k++) {
var state = svg.append("g")
    .attr("class", "g")
    .attr("transform", function (d) {
        return "translate(" + x(data.bars[k].year) + ",0)";
    });
state.selectAll("rect")
    .data(data.bars[k].population)
    .enter().append("rect")
//.attr("width", x.rangeBand())
.attr("class", "rect_grp" + k)
    .attr("id", function (d, i) {
        return "rect" + i;
    })
    .attr("width", function () {
        return x.rangeBand();
    })
    .attr("y", function (d, i) { /*console.log("hiii");*/
        if (i != 0) {
            var prevHgt = d3.select(".rect_grp" + k + "#rect" + (i - 1)).attr("height"); // Select height of previous rectangle
            var ylimit = d3.select(".rect_grp" + k + "#rect" + (i - 1)).attr("y"); // Select y of previous rectangle
            console.log("prevHgt=>" + prevHgt);
            return ((parseFloat(ylimit)) - (parseFloat(prevHgt)));
        } else {
            return y(d.strength);
        }
    })
    .attr("height", function (d, i) {
        return (Math.round(y(yAxMin_PA)) - Math.round(y(d.strength)));
    })
    .style("fill", function (d, i) {
        console.log(i);
        return color(i);
    });

}

</script>

我发现给人们举例而不是让他们自己运行是很有用的。看这里:http://tributary.io/inlet/5835233。

在第 157 行附近,它说

d.population.forEach (function(d){
  color.domain(d3.keys(d).filter(function(name) {
  return name;
}

name总是"category""strength"。这是因为数据的排列方式。我认为你想要的是让你的数据

{year: 2008, 
population: {
    category1: 20,
    category2: 43,
    category3: 55}
}

如果你像这样放置数据,你将不得不弄乱你如何精确地设置color实例的域,因为forEach只适用于数组,我们现在将数据设置为在对象中。像color.domain(d3.keys(d.population)).在支流上分叉我的例子并尝试几件事。查看d3.keys()文档以了解其工作原理。