如何删除 d3.js 分组条形图中条形之间的空格

问题描述 投票:0回答:1

我有以下 d3.js 代码,有助于创建分组条形图。我的数据由不同的州及其按年龄类别划分的人口组成。在此数据中,“德克萨斯州”和“纽约州”缺少几个年龄类别(14 至 17 岁、18 至 24 岁、25 至 44 岁)。因此,当我们使用这些数据创建分组条形图时,它会在条形之间创建空白空间以容纳丢失的数据。我们如何摆脱 d3.js 中条形图之间缺失数据的空白区域。 我在github中发现了同样的问题,但没有人给出解决方案。

@mbostock @jasondavies @gordonwoodhull @esjewett @vogievetsky @jheer @connorgr @Fil @petulla @tmcw @shikhaagrawal23 @gkumar100


<!DOCTYPE html>
<style>

.axis .domain {
 display: none;
}

</style>
<svg width="960" height="500"></svg>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>

var svg = d3.select("svg"),
   margin = {top: 20, right: 20, bottom: 30, left: 40},
   width = +svg.attr("width") - margin.left - margin.right,
   height = +svg.attr("height") - margin.top - margin.bottom,
   g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");

var x0 = d3.scaleBand()
   .rangeRound([0, width])
   .paddingInner(0.1);

var x1 = d3.scaleBand()
   .padding(0.05);

var y = d3.scaleLinear()
   .rangeRound([height, 0]);

var z = d3.scaleOrdinal()
   .range(["#98abc5", "#8a89a6", "#7b6888", "#6b486b", "#a05d56", "#d0743c", "#ff8c00"]);
   
   
var data = [
 {
   "State": "CA",
   "Under 5 Years": 2704659,
   "5 to 13 Years": 4499890,
   "14 to 17 Years": 2159981,
   "18 to 24 Years": 3853788,
   "25 to 44 Years": 10604510,
   "45 to 64 Years": 8819342,
   "65 Years and Over": 4114496
 },
 {
   "State": "TX",
   "Under 5 Years": 2027307,
   "5 to 13 Years": 3277946,   
   "45 to 64 Years": 5656528,
   "65 Years and Over": 2472223
 },
 {
   "State": "NY",
   "Under 5 Years": 1208495,
   "5 to 13 Years": 2141490,    
   "25 to 44 Years": 5355235,
   "45 to 64 Years": 5120254,
   "65 Years and Over": 2607672
 },
 {
   "State": "FL",
   "Under 5 Years": 1140516,
   "5 to 13 Years": 1938695,
   "14 to 17 Years": 925060,
   "18 to 24 Years": 1607297,
   "25 to 44 Years": 4782119,
   "45 to 64 Years": 4746856,
   "65 Years and Over": 3187797
 },
 {
   "State": "IL",
   "Under 5 Years": 894368,
   "5 to 13 Years": 1558919,
   "14 to 17 Years": 725973,
   "18 to 24 Years": 1311479,
   "25 to 44 Years": 3596343,
   "45 to 64 Years": 3239173,
   "65 Years and Over": 1575308
 },
 {
   "State": "PA",
   "Under 5 Years": 737462,
   "5 to 13 Years": 1345341,
   "14 to 17 Years": 679201,
   "18 to 24 Years": 1203944,
   "25 to 44 Years": 3157759,
   "45 to 64 Years": 3414001,
   "65 Years and Over": 1910571
 }
];

 var keys  = Object.keys(data[0]);
  keys = keys.slice(1);

 x0.domain(data.map(function(d) { return d.State; }));
 x1.domain(keys).rangeRound([0, x0.bandwidth()]);
 y.domain([0, d3.max(data, function(d) { return d3.max(keys, function(key) { return d[key]; }); })]).nice();

 g.append("g")
   .selectAll("g")
   .data(data)
   .enter().append("g")
     .attr("transform", function(d) { return "translate(" + x0(d.State) + ",0)"; })
   .selectAll("rect")
   .data(function(d) { return keys.map(function(key) { return {key: key, value: d[key]}; }); })
   .enter().append("rect")
     .attr("x", function(d) { return x1(d.key); })
     .attr("y", function(d) { return y(d.value); })
     .attr("width", x1.bandwidth())
     .attr("height", function(d) { return height - y(d.value); })
     .attr("fill", function(d) { return z(d.key); });

 g.append("g")
     .attr("class", "axis")
     .attr("transform", "translate(0," + height + ")")
     .call(d3.axisBottom(x0));

 g.append("g")
     .attr("class", "axis")
     .call(d3.axisLeft(y).ticks(null, "s"))
   .append("text")
     .attr("x", 2)
     .attr("y", y(y.ticks().pop()) + 0.5)
     .attr("dy", "0.32em")
     .attr("fill", "#000")
     .attr("font-weight", "bold")
     .attr("text-anchor", "start")
     .text("Population");

 var legend = g.append("g")
     .attr("font-family", "sans-serif")
     .attr("font-size", 10)
     .attr("text-anchor", "end")
   .selectAll("g")
   .data(keys.slice().reverse())
   .enter().append("g")
     .attr("transform", function(d, i) { return "translate(0," + i * 20 + ")"; });

 legend.append("rect")
     .attr("x", width - 19)
     .attr("width", 19)
     .attr("height", 19)
     .attr("fill", z);

 legend.append("text")
     .attr("x", width - 24)
     .attr("y", 9.5)
     .attr("dy", "0.32em")
     .text(function(d) { return d; });
</script>
</html>


javascript d3.js
1个回答
0
投票

我付出了很多努力来解决这个问题,并尝试使你的代码动态化以适应各种情况。请检查一下。

var svg = d3.select("svg"),
   margin = {top: 20, right: 20, bottom: 30, left: 40},
   width = +svg.attr("width") - margin.left - margin.right,
   height = +svg.attr("height") - margin.top - margin.bottom,
   g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");

var x0 = d3.scaleBand()
   .rangeRound([0, width])
   .paddingInner(0.1);

var x1 = d3.scaleBand()
   .padding(0.05);

var y = d3.scaleLinear()
   .rangeRound([height, 0]);

var z = d3.scaleOrdinal()
   .range(["#98abc5", "#8a89a6", "#7b6888", "#6b486b", "#a05d56", "#d0743c", "#ff8c00"]);
   
   
var data = [
 {
   "State": "CA",
   "Under 5 Years": 2704659,
   "5 to 13 Years": 4499890,
   "14 to 17 Years": 2159981,
   "18 to 24 Years": 3853788,
   "25 to 44 Years": 10604510,
   "45 to 64 Years": 8819342,
   "65 Years and Over": 4114496
 },
 {
   "State": "TX",
   "Under 5 Years": 2027307,
   "5 to 13 Years": 3277946,   
   "45 to 64 Years": 5656528,
   "65 Years and Over": 2472223
 },
 {
   "State": "NY",
   "Under 5 Years": 1208495,
   "5 to 13 Years": 2141490,    
   "25 to 44 Years": 5355235,
   "45 to 64 Years": 5120254,
   "65 Years and Over": 2607672
 },
 {
   "State": "FL",
   "Under 5 Years": 1140516,
   "5 to 13 Years": 1938695,
   "14 to 17 Years": 925060,
   "18 to 24 Years": 1607297,
   "25 to 44 Years": 4782119,
   "45 to 64 Years": 4746856,
   "65 Years and Over": 3187797
 },
 {
   "State": "IL",
   "Under 5 Years": 894368,
   "5 to 13 Years": 1558919,
   "14 to 17 Years": 725973,
   "18 to 24 Years": 1311479,
   "25 to 44 Years": 3596343,
   "45 to 64 Years": 3239173,
   "65 Years and Over": 1575308
 },
 {
   "State": "PA",
   "Under 5 Years": 737462,
   "5 to 13 Years": 1345341,
   "14 to 17 Years": 679201,
   "18 to 24 Years": 1203944,
   "25 to 44 Years": 3157759,
   "45 to 64 Years": 3414001,
   "65 Years and Over": 1910571
 }
];


  var legthList = data.map((d,i) => {
   return Object.keys(d).length
  });
  var maxLegth = (Math.max(...legthList)-1)
  
  var findMaxObjPro = data.filter((el => Object.keys(el).length === maxLegth+1))
  
  var keys  = Object.keys(findMaxObjPro[0]);
  keys = keys.slice(1);
  
 x0.domain(data.map(function(d) { return d.State; }));
 x1.domain(keys).rangeRound([0, x0.bandwidth()]);
 y.domain([0, d3.max(data, function(d) { return d3.max(keys, function(key) { return d[key]; }); })]).nice();

 g.append("g")
   .selectAll("g")
   .data(data)
   .enter().append("g")
     .attr("transform", function(d) { 
     let {State,...rest} = d
     let localKeys = Object.keys(rest)
     let bandwidth = (x1.bandwidth()*(maxLegth-localKeys.length))/2;
     return "translate(" + (x0(d.State)+bandwidth) + ",0)"; 
     })
   .selectAll("rect")
   .data(function(d) { 
    // remove State field
    let {State,...rest} = d
    let localKeys = Object.keys(rest)
    return localKeys.map(function(key) { return {key: key, value: d[key]}; }); })
   .enter().append("rect")
     .attr("x", function(d,i) {
      return (x1(keys[0]) + i*(x1.bandwidth())) 
     })
     .attr("y", function(d) { return y(d.value); })
     .attr("width", x1.bandwidth())
     .attr("height", function(d) { return height - y(d.value); })
     .attr("fill", function(d) { return z(d.key); });

 g.append("g")
     .attr("class", "axis")
     .attr("transform", "translate(0," + height + ")")
     .call(d3.axisBottom(x0));

 g.append("g")
     .attr("class", "axis")
     .call(d3.axisLeft(y).ticks(null, "s"))
   .append("text")
     .attr("x", 2)
     .attr("y", y(y.ticks().pop()) + 0.5)
     .attr("dy", "0.32em")
     .attr("fill", "#000")
     .attr("font-weight", "bold")
     .attr("text-anchor", "start")
     .text("Population");

 var legend = g.append("g")
     .attr("font-family", "sans-serif")
     .attr("font-size", 10)
     .attr("text-anchor", "end")
   .selectAll("g")
   .data(keys.slice().reverse())
   .enter().append("g")
     .attr("transform", function(d, i) { return "translate(0," + i * 20 + ")"; });

 legend.append("rect")
     .attr("x", width - 19)
     .attr("width", 19)
     .attr("height", 19)
     .attr("fill", z);

 legend.append("text")
     .attr("x", width - 24)
     .attr("y", 9.5)
     .attr("dy", "0.32em")
     .text(function(d) { return d; });
.axis .domain {
 display: none;
}
<svg width="960" height="500"></svg>
<script src="https://d3js.org/d3.v4.min.js"></script>

© www.soinside.com 2019 - 2024. All rights reserved.