English |  Español |  Français |  Italiano |  Português |  Русский |  Shqip

Developing a D3.js Edge

11. Integrating Crossfilter

  • Use Crossfilter to filter our stop metric data
  • Create aggregate statistics on these filtered locations

 The source code and data files are available in the code/Chapter11/ directory tree.

Now that we have our brushing setup for our maps and it returns an array that can be accepted by the filterLocation filter we defined earlier, we can easily integrate the two so that brushing over the map will filter our stop metric data. We can do this simply by passing in the extents of our brush, obtained by brush.extent(), into our filter function.

001:zurichMap.on('brushing'function (brush) {
002:    var filteredLocations = zurichDataManager.filterLocation(brush.extent());

Every time we brush over the map, the extents of our brush will be passed into our filter function and assigned to the local variable filteredLocations. We can now perform some aggregate statistics on these filtered locations and pass them into the radial histogram we will develop in the next chapter. Let's take a look how we will generate these statistics.

Just the same way we created a method in our data manager module to filter by locations, we will create another method that we can use to filter and aggregate the data by stop delays. We will setup our method like so:

001:// Create a getDelays method to filter and aggregate the delay data by stop.
002:exports.getDelay = function (_locations) {
003:    //...

Filtering with Crossfilter

For this method we are going to pass in our filtered locations as the only argument. Since this is just an array of locations, we can create another Crossfilter within our new method to filter, group, and reduce on. We do this since we want Crossfilter to remain local to this method. Otherwise, if we used a Crossfilter defined at the top of our module definition, every time we brushed over the map we would be adding data to the Crossfilter. By defining it locally, we ensure that the Crossfilter only contains data for the area that we have selected. The code looks like this:

001:// Create a getDelays method to filter and aggregate the delay data by stop.
002:exports.getDelay = function (_locations) {
003:    var delayCrossfilter = crossfilter(),
004:    // Create a dimension by hour of the scheduled stop time.
005:    stopTime = delayCrossfilter.dimension(function (d) {
006:        return d.SCHEDULED.getHours();
007:    });
008:    // Group the dimension by hour, and reduce it by increasing the count for all delays greater than 1.
009:    lateArrivalsByStopTime = stopTime.group().reduce(
010:        function reduceAdd(p, v) {
011:            return v.DELAY > 0 ? p + 1 : p + 0;
012:        },
013:        function reduceRemove(p,v) { return 0; },
014:        function reduceInitial(p,v) { return 0; }
015:    );
016:    // Add our filtered locations to the crossfilter.
017:    delayCrossfilter.add(_locations);
018:    // Return an array contained the aggregated data, and the stopTime dimension.
019:    return [stopTime, lateArrivalsByStopTime];

What this method is doing is creating a dimension based upon the hour of the scheduled stop time. It is then grouping all of the selected stops by this dimension and then reducing all of these records to a single value for each hour. This value is computed simply by incrementing the count if the delay is greater than one. What we will end up with is a count for every hour containing all of the transit stops events that were delayed for a given set of locations. The reason we return an array containing both the group and the dimension is we will want access to both of these later when we construct our radial histogram. Now we can inspect the data like this:

001:zurichMap.on('brushing'function (brush) {
002:    var filteredLocations = zurichDataManager.filterLocation(brush.extent());
003:    delaysByHourAndLocation = zurichDataManager.getDelays(filteredLocations);
004:    // Inspect the total number of events by hour;
005:    console.log(delaysByHourAndLocation[0].group().all());
006:    // Inspect the total number of delays by hour.
007:    console.log(delaysByHourAndLocation[1].all());


Now, when you brush over the map you should see the data in the console for the area you have selected. Our next and final step is to develop the radial histogram to visualize this data and update it every time we brush over the map, shown in the next chapter.

There has been error in communication with Booktype server. Not sure right now where is the problem.

You should refresh this page.