July 2014

Plotting non-uniform time data with D3.js

For a typical time-series data, one would use the d3.time.scale scale. This scale, however, does not work for plotting non-uniform time-series data (for eg. market data) where weekend days show as gaps and are undesirable.

d3.time.scale example

The easy way around this is to map weekdays onto a uniform scale and use the linear scale to plot it. There is a great example for this by Mike Bostock in weekday.js gist. Simple tick formatting can be added to show proper dates instead of the weekday numbers:

var dateFormat = d3.time.format('%a %b %d');
xAxis.tickFormat(function (d) { return dateFormat(weekday.invert(d));});
Static tickmarks

So far so good, but now the dynamic tick format that comes with d3.time.scale scale is lost. The easiest way to get this functionality back is to yank the code from d3.time.scale and do some slight adjustments to make it work with our interpretations of days (d3_time_scaleLocalFormat, scale.ticks, and associated functions). These can then be used as follows:

xAxis
  .tickFormat(my_time_scaleLocalFormat)
  .tickValues(my_scale_ticks);

Unfortunately, some these functions can’t be reused, as they are declared as private, and others need slight modifications to cope with weekdays instead of Date objects. For simple one-off use, the above solution is probably good enough, but if you need ease of reuse or have more complex application, it might be easier to wrap this up as a standalone scale.

Finished example

The scale takes a mapping function as a parameter, and produces a scale with dynamic date-based tics like the d3.time.scale scale does.

One addition to Mike’s weekday example was caching. For small data sets it works well, but With a couple of axes, brush, and a few years worth of weekday data, the conversion was getting noticeable.

The final code, including an example, modified weekday.js and the d3.scale.dayselect scale can be found in the Dayselect Scale block (or Gist).

One caveat with this method is when using brush, the extent of the brush is returned as date objects, but they are really integers representing weekdays on the uniform scale. This can be easily fixed by prepending a plus sign (+) before it, or doing a math operation on the values: +brush.extent()[0] or brush.extent()[0] * 1.

May 2014

“There is no problem so bad, that you can't make it worse.” #

— Chris Hadfield (quoting an astronaut saying)

April 2014

Sunshine!

Sunrise over Vancouver's north shore. © Mayo Jordanov
January 2014

Vancouver

Cloudy sunset over downtown Vancouver. © Mayo Jordanov
November 2013
September 2013
August 2013
March 2013

Vancouver

View of Vancouver lit up in evening glow. Cypress Mountain viewpoint, Vancouver, BC. © Mayo Jordanov
January 2013

Fire In The Sky

Sunset over Whistler, Black Tusk, and the Tantalus Range on the way back from Blackcomb backcountry. Whistler, BC. © Mayo Jordanov

“The only Zen you'll find on mountain tops is the Zen you bring up there with you.” #

— Alan Watts

Mayo Jordanov is a computer programmer and enthusiast based out of Vancouver, British Columbia. Mayo is currently working as a programmer for a company specializing in electrical grid optimization solutions. On side, he dabbles with photography, design, servers, and various web technologies.

Comments? Tweet @oyam, or email mayo@… PGP key: 0xDDCAFEE6.

Powered by Mercurial and Hyde static site generator.