<!DOCTYPE html>
<html>
<head>
<script data-require="d3@*" data-semver="4.0.0" src="https://d3js.org/d3.v4.min.js"></script>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<h1>Histogram</h1>
<div class="charts"></div>
<script src="script.js"></script>
</body>
</html>
var data = [61, 139, 218, 258, 282, 284, 285, 285, 291, 311, 319, 320, 336, 341, 345, 345, 371, 380, 381, 384, 412, 421, 488, 511, 512, 522, 598, 613, 684, 730, 780, 902, 1015, 1219, 1479, 1533, 1939, 83168, 1261736, 1280703];
// var data = data.slice(0, Math.floor((data.length-1)*.90));
var tripDurationHistogram = histogramChart();
var container = d3.select('.charts');
container.append('svg').datum(data).call(tripDurationHistogram);
// https://bl.ocks.org/mbostock/3048450
// https://bl.ocks.org/mbostock/3048166
// https://bl.ocks.org/mbostock/b2fee5dae98555cf78c9e4c5074b87c3
function histogramChart() {
var margin = {top: 10, right: 30, bottom: 30, left: 30},
width = 460 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom,
title = '';
var preprocessor = function(d) { return d };
function chart(selection) {
selection.each(function(raw, i) {
// generate chart here; `raw` is the data and `this` is the element
var chart = d3.select(this)
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
// Title
d3.select(this).append('g')
.attr("transform", "translate(" + width/2 + ", " + (margin.top - 5) + ")")
.append('text')
.attr('class', 'title')
.text(title);
// preparing data
var data = preprocessor(raw);
// var data = d3.range(1000).map(d3.randomBates(10));
var formatCount = d3.format(",.0f");
//
// var x = d3.scaleLinear()
// .domain([0, d3.quantile(data, 0.95)])
// .rangeRound([0, width]);
// var bins = d3.histogram()
// .domain(x.domain())
// .thresholds(x.ticks(20))(data);
//
var MIN = 60;
var HR = MIN * 60;
var tripDomain = [0, 15*MIN, 30*MIN, 45*MIN, 60*MIN, 90*MIN, Math.max(24*HR, d3.max(data))];
var bins = d3.histogram()
.thresholds(tripDomain)(data);
var x = d3.scaleOrdinal()
.domain(tripDomain)
.range(tripDomain.map((_,i) => (i/(tripDomain.length-1))*width));
// console.debug(data, bins, x.domain());
var y = d3.scaleLinear()
.domain([0, d3.max(bins, function(d) { return d.length; })])
.range([height, 0]);
// bars
var bar = chart.selectAll(".bar")
.data(bins);
bar.exit().remove();
var newBar = bar.enter()
.append("g")
.attr('class', 'bar')
.attr("transform", function(d) { return "translate(" + x(d.x0) + "," + y(d.length) + ")"; });
newBar.append('rect');
newBar.append('text');
var all = newBar.merge(bar);
all.select('rect')
.attr("x", 1)
.attr("width", x(bins[0].x1) - x(bins[0].x0) - 1)
.attr("height", function(d) { return height - y(d.length); });
all.select("text")
.attr("dy", ".75em")
.attr("y", 6)
.attr("x", (x(bins[0].x1) - x(bins[0].x0)) / 2)
.attr("text-anchor", "middle")
.text(function(d) { return formatCount(d.length); });
chart.append("g")
.attr("class", "axis axis--x")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x));
});
}
chart.title = function(_) {
return arguments.length ? (title = _, chart) : title;
};
// https://bost.ocks.org/mike/chart/
chart.preprocessor = function(_) {
return arguments.length ? (preprocessor = _, chart) : preprocessor;
};
chart.width = function(_) {
return arguments.length ? (width = _, chart) : width;
};
chart.height = function(_) {
return arguments.length ? (height = _, chart) : height;
};
return chart;
}
.bar text {
fill: white;
font: 10px sans-serif;
text-anchor: end;
}
.bar {
fill: steelblue;
}
.axis text {
font: 10px sans-serif;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.x.axis path {
display: none;
}