Build Interactive Report with Crossfilter and dc.js

http://shzhangji.com

by zjerryj

HTML

<link rel="stylesheet" href="https://unpkg.com/dc@2.1.3/dc.css">
<script src="https://unpkg.com/lodash@4.17.4/lodash.js"></script>
<script src="https://unpkg.com/moment@2.18.0/moment.js"></script>
<script src="https://unpkg.com/crossfilter@1.3.12/crossfilter.js"></script>
<script src="https://unpkg.com/d3@3.5.17/d3.js"></script>
<script src="https://unpkg.com/dc@2.1.3/dc.js"></script>
<h2>Example: Airline on-time performance</h2>

<div id="hour-chart">
  <div class="title">Time of Day
    <a class="reset" href="javascript:;" style="visibility: hidden;">reset</a>
  </div>
</div>

<div id="delay-chart">
  <div class="title">Arrival Delay (min.)
    <a class="reset" href="javascript:;" style="visibility: hidden;">reset</a>
  </div>
</div>

<div id="distance-chart">
  <div class="title">Distance (mi.)
    <a class="reset" href="javascript:;" style="visibility: hidden;">reset</a>
  </div>
</div>

<div style="clear: both;"></div>

<div id="date-chart">
  <div class="title">Date
    <a class="reset" href="javascript:dateChart.filterAll();dc.redrawAll();" style="visibility: hidden;">reset</a>
  </div>
</div>

<div style="clear: both;"></div>

<div id="flight-table" style="float: left;">
  <table></table>
</div>

<div id="data-count" style="float: left; margin: 30px;"></div>

<div id="flights-csv" style="display:...

CSS

#flight-table table {
  border-collapse: collapse;
}

#flight-table table .dc-table-head {
  display: none;
}

#flight-table table .dc-table-label {
  padding: 5px;
}

#flight-table table .dc-table-row {
  background-color: #eee;
  border-bottom: 2px solid white;
}

#flight-table table .dc-table-column {
  width: 100px;
  padding: 5px;
}

#flight-table table .dc-table-column._3 {
  text-align: right;
}

#flight-table table .dc-table-column._4 {
  text-align: right;
}

JavaScript

let flightsCsv = document.getElementById('flights-csv').innerHTML.trim()
let flights = d3.csv.parse(flightsCsv)

_.forEach(flights, (d, i) => {
  d.index = i
  d.date = moment('2001' + d.date, 'YYYYMMDDHHmm').toDate()
  d.delay = +d.delay
  d.distance = +d.distance
})

let flight = crossfilter(flights)
let hour = flight.dimension((d) => d.date.getHours() + d.date.getMinutes() / 60)
let hours = hour.group(Math.floor)
let delay = flight.dimension((d) => Math.max(-60, Math.min(149, d.delay)) / 10)
let delays = delay.group(Math.floor)
let distance = flight.dimension((d) => Math.min(1999, d.distance) / 50)
let distances = distance.group(Math.floor)
let date = flight.dimension((d) => d.date)
let dates = date.group(d3.time.day)

let hourChart = dc.barChart('#hour-chart')
hourChart
  .width(350)
  .height(150)
  .dimension(hour)
  .group(hours)
  .x(d3.scale.linear()
    .domain([0, 23])
    .rangeRound([0, 10 * 24]))
  .controlsUseVisibility(true)
hourChart.yAxis().tickFormat(d3.format('s'))

let delayChart = dc.barChart('#delay-chart')
delayChart
  .width(350)
  .height(150)
  .dimension(delay)
  .group(delays)
  .x(d3.scale.linear()
    .domain([-6, 15])
    .rangeRound([0, 10 * 21]))
  .controlsUseVisibility(true)
delayChart.xAxis().tickFormat((d) => d * 10)
delayChart.yAxis().tickFormat(d3.format('s'))

let distanceChart = dc.barChart('#distance-chart')
distanceChart
  .width(450)
  .height(150)
  .dimension(distance)
  .group(distances)
  .x(d3.scale.linear()
    .domain([0, 2000 / 50])
    .rangeRound(0, 10 * 40))
  .controlsUseVisibility(true)
distanceChart.xAxis().tickFormat((d) => d * 50)
distanceChart.yAxis().tickFormat(d3.format('s'))

let dateChart = dc.barChart('#date-chart')
dateChart
  .width(1150)
  .height(180)
  .dimension(date)
  .group(dates)
  .x(d3.time.scale()
    .domain([new Date(2001, 0, 1), new Date(2001, 3, 1)])
    .rangeRound([0, 10 * 90]))
  .round(d3.time.day.round)
  .xUnits(d3.time.days)
 ...