【问题标题】:Histogram using d3js使用 d3js 的直方图
【发布时间】:2017-09-07 22:32:19
【问题描述】:

我正在尝试为收入范围中断创建一个直方图,并在每个中断中包含计数。我从一个基本的直方图块中选择了这个例子。下面是这个的代码。如何生成直方图以在 x 轴上显示收入范围并在 y 上计数。

https://jsfiddle.net/snt1/cLu6f1nb/6/

var margin = {
  top: 30,
  right: 20,
  bottom: 30,
  left: 50
};
var width = 600 - margin.left - margin.right;
var height = 270 - margin.top - margin.bottom;


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 + ")");

// Get the data
var all = [{
  "name": "Home Value",
  "code": "HOME_VALUE",
  "children": [{
    "name": "Housing Value   Under $10,000",
    "code": "Q084002",
    "count": 78
  }, {
    "name": "Housing Value  $10,000 to $14,999",
    "code": "Q084003",
    "count": 73
  }, {
    "name": "Housing Value  $15,000 to $19,999",
    "code": "Q084004",
    "count": 30
  }, {
    "name": "Housing Value  $20,000 to $25,000",
    "code": "Q084005",
    "count": 60
  }, {
    "name": "Housing Value  $25,000 to $29,999",
    "code": "Q084006",
    "count": 40
  }, {
    "name": "Housing Value  $30,000 to $34,999",
    "code": "Q084007",
    "count": 21
  }, {
    "name": "Housing Value  $35,000 to $39,999",
    "code": "Q084008",
    "count": 8
  }, {
    "name": "Housing Value  $40,000 to $49,999",
    "code": "Q084009",
    "count": 44
  }, {
    "name": "Housing Value  $50,000 to $59,999",
    "code": "Q084010",
    "count": 85
  }, {
    "name": "Housing Value  $60,000 to $69,999",
    "code": "Q084011",
    "count": 93
  }, {
    "name": "Housing Value  $70,000 to $79,999",
    "code": "Q084012",
    "count": 208
  }, {
    "name": "Housing Value  $80,000 to $89,999",
    "code": "Q084013",
    "count": 231
  }, {
    "name": "Housing Value  $90,000 to $99,999",
    "code": "Q084014",
    "count": 419
  }, {
    "name": "Housing Value $100,000 to $124,999",
    "code": "Q084015",
    "count": 1491
  }, {
    "name": "Housing Value $125,000 to $149,999",
    "code": "Q084016",
    "count": 1135
  }, {
    "name": "Housing Value $150,000 to $174,999",
    "code": "Q084017",
    "count": 866
  }, {
    "name": "Housing Value $175,000 to $199,999",
    "code": "Q084018",
    "count": 472
  }, {
    "name": "Housing Value $200,000 to $249,999",
    "code": "Q084019",
    "count": 654
  }, {
    "name": "Housing Value $250,000 to $299,999",
    "code": "Q084020",
    "count": 536
  }, {
    "name": "Housing Value $300,000 to $399,999",
    "code": "Q084021",
    "count": 409
  }, {
    "name": "Housing Value $400,000 to $499,999",
    "code": "Q084022",
    "count": 145
  }, {
    "name": "Housing Value $500,000 to $749,999",
    "code": "Q084023",
    "count": 147
  }, {
    "name": "Housing Value $750,000 to $999,999",
    "code": "Q084024",
    "count": 128
  }]
}]
var data = all[0].children;

data.forEach(function(d) {
  d.name = +d.name;
  d.count = +d.count;
});
var x = d3.scaleLinear()
  .rangeRound([0, width]);

var y = d3.scaleLinear()
  .domain([0, d3.max(bins, function(d) {
    return d.count;
  })])
  .range([height, 0]);

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 x = d3.scaleLinear()
  .rangeRound([0, width]);

var bins = d3.histogram()
  .domain(x.domain())
  .thresholds(x.ticks(20))
  (data);

var y = d3.scaleLinear()
  .domain([0, d3.max(bins, function(d) {
    return d.count;
  })])
  .range([height, 0]);
// Coerce types.

data.forEach(function(bin) {
  bin.name = +bin.name;
  bin.count = +bin.count;
});

// Normalize each bin to so that height = quantity/width;
// see http://en.wikipedia.org/wiki/Histogram#Examples
for (var i = 1, n = bins.length, bin; i < n; i++) {
  bin = bins[i];
  bin.offset = bins[i - 1].name;
  bin.width = bin.name - bin.offset;
  bin.height = bin.count / bin.width;
}

// Drop the first bin, since it's incorporated into the next.
bins.shift();

// Set the scale domain.
x.domain([0, d3.max(bins.map(function(d) {
  return d.offset + d.width;
}))]);
y.domain([0, d3.max(bins.map(function(d) {
  return d.height;
}))]);

// Add the bins.
svg.selectAll(".bin")
  .data(data)
  .enter().append("rect")
  .attr("class", "bin")
  .attr("x", function(d) {
    return x(d.offset);
  })
  .attr("width", function(d) {
    return x(d.width) - 1;
  })
  .attr("y", function(d) {
    return y(d.height);
  })
  .attr("height", function(d) {
    return height - y(d.height);
  });

svg.append("g")
  .attr("class", "x axis")
  .attr("transform", "translate(0," + height + ")")
  .call(d3.svg.axis()
    .scale(x)
    .orient("bottom"));

svg.append("g")
  .attr("class", "y axis")
  .call(d3.svg.axis()
    .scale(y)
    .orient("left"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.10.2/d3.js"></script>
<body></body>

【问题讨论】:

    标签: d3.js charts histogram


    【解决方案1】:

    您的问题/代码的问题是对什么是条形图和什么是直方图的误解。别难过,很多人都搞错了。

    正如我在another answer 中所说:条形图本质上是由代表分类变量的条形组成的。这意味着条形图位于代表分类变量的标签上,即 定性 变量。当我说“很多人都搞错了”时,我说的是条形图和直方图之间的区别:两者都使用矩形来编码数据,但在直方图中,与条形图不同,标签代表一个定量变量。每个月至少有六次我在 S.O. 见到某人。发布一个关于 histograms 实际上是条形图的问题,或关于 bar chart 实际上是直方图的问题。

    回到您的问题:您的数据不适合直方图。正如我所说,直方图代表一个定量变量。因此,这对于直方图来说是足够的数据:

    [{
      value: 200000,
      code: "Q084001"
    }, {
      value: 250000,
      code: "Q084002"
    }, {
      value: 180000,
      code: "Q084003"
    }, {
      value: 490000,
      code: "Q084001"
    },
    //etc...
    ]
    

    有了这样的数据,您可以根据变量value,按照您想要的方式创建垃圾箱。

    但是,现在,您有分类变量,它们是:

    ["Housing Value Under $10,000", 
      "Housing Value $10,000 to $14,999", 
      "Housing Value $15,000 to $19,999", 
      //etc...
    ];
    

    无法使用此数据创建直方图。

    解决方案:只需创建一个好的旧条形图即可。

    这是一个条形图,其中包含您的数据和代码中的最小更改:

    var margin = {
      top: 30,
      right: 20,
      bottom: 180,
      left: 50
    };
    var width = 600 - margin.left - margin.right;
    var height = 370 - margin.top - margin.bottom;
    
    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 + ")");
    
    // Get the data
    var all = [{
      "name": "Home Value",
      "code": "HOME_VALUE",
      "children": [{
        "name": "Housing Value   Under $10,000",
        "code": "Q084002",
        "count": 78
      }, {
        "name": "Housing Value  $10,000 to $14,999",
        "code": "Q084003",
        "count": 73
      }, {
        "name": "Housing Value  $15,000 to $19,999",
        "code": "Q084004",
        "count": 30
      }, {
        "name": "Housing Value  $20,000 to $25,000",
        "code": "Q084005",
        "count": 60
      }, {
        "name": "Housing Value  $25,000 to $29,999",
        "code": "Q084006",
        "count": 40
      }, {
        "name": "Housing Value  $30,000 to $34,999",
        "code": "Q084007",
        "count": 21
      }, {
        "name": "Housing Value  $35,000 to $39,999",
        "code": "Q084008",
        "count": 8
      }, {
        "name": "Housing Value  $40,000 to $49,999",
        "code": "Q084009",
        "count": 44
      }, {
        "name": "Housing Value  $50,000 to $59,999",
        "code": "Q084010",
        "count": 85
      }, {
        "name": "Housing Value  $60,000 to $69,999",
        "code": "Q084011",
        "count": 93
      }, {
        "name": "Housing Value  $70,000 to $79,999",
        "code": "Q084012",
        "count": 208
      }, {
        "name": "Housing Value  $80,000 to $89,999",
        "code": "Q084013",
        "count": 231
      }, {
        "name": "Housing Value  $90,000 to $99,999",
        "code": "Q084014",
        "count": 419
      }, {
        "name": "Housing Value $100,000 to $124,999",
        "code": "Q084015",
        "count": 1491
      }, {
        "name": "Housing Value $125,000 to $149,999",
        "code": "Q084016",
        "count": 1135
      }, {
        "name": "Housing Value $150,000 to $174,999",
        "code": "Q084017",
        "count": 866
      }, {
        "name": "Housing Value $175,000 to $199,999",
        "code": "Q084018",
        "count": 472
      }, {
        "name": "Housing Value $200,000 to $249,999",
        "code": "Q084019",
        "count": 654
      }, {
        "name": "Housing Value $250,000 to $299,999",
        "code": "Q084020",
        "count": 536
      }, {
        "name": "Housing Value $300,000 to $399,999",
        "code": "Q084021",
        "count": 409
      }, {
        "name": "Housing Value $400,000 to $499,999",
        "code": "Q084022",
        "count": 145
      }, {
        "name": "Housing Value $500,000 to $749,999",
        "code": "Q084023",
        "count": 147
      }, {
        "name": "Housing Value $750,000 to $999,999",
        "code": "Q084024",
        "count": 128
      }]
    }]
    var data = all[0].children;
    
    
    // Set the scale domain.
    
    var x = d3.scaleBand()
      .rangeRound([0, width])
      .domain(data.map(function(d) {
        return d.name;
      }))
      .padding(0.2);
    
    var y = d3.scaleLinear()
      .domain([0, d3.max(data, function(d) {
        return d.count;
      })])
      .range([height, 0]);
    
    // Add the bins.
    svg.selectAll(null)
      .data(data)
      .enter()
      .append("rect")
      .attr("fill", "steelblue")
      .attr("x", function(d) {
        return x(d.name);
      })
      .attr("width", function(d) {
        return x.bandwidth();
      })
      .attr("y", function(d) {
        return y(d.count);
      })
      .attr("height", function(d) {
        return height - y(d.count);
      });
    
    svg.append("g")
      .attr("class", "x axis")
      .attr("transform", "translate(0," + height + ")")
      .call(d3.axisBottom(x))
      .selectAll("text")
      .attr("transform", "translate(-12,86) rotate(-90)");
    
    svg.append("g")
      .attr("class", "y axis")
      .call(d3.axisLeft(y));
    &lt;script src="https://d3js.org/d3.v4.min.js"&gt;&lt;/script&gt;

    【讨论】:

      猜你喜欢
      • 2023-03-24
      • 2021-03-31
      • 2018-03-30
      • 1970-01-01
      • 2011-01-29
      • 1970-01-01
      • 2014-02-15
      相关资源
      最近更新 更多