D3.js Grouped column chart with selective categories

What was the last time you tried to make a grouped column chart with variable number of categories in user selection? Im sure you have struggled with the scale calculations and with keeping the grouped columns centered on the ticks on the axis ?

I tried understanding what they say here : mbostock and also tried to make sense what they narrate here ordinal scales. You need not comprehend the entire linear mathematics to grasp the idea behind this diagram

68747470733a2f2f662e636c6f75642e6769746875622e636f6d2f6173736574732f3233303534312f3533383638382f34366332393863302d633139332d313165322d396137652d3135643961626366616239622e706e67.png
Here is a clean explanation of how the rangeRoundBands( ) work when using the ordinal scale

Building the chart with fixed number of categories on the X-axis would be one time calculation. For variable number of categories each time your code then needs to adjust to changes and center the group of columns on the axis tick

Scenario :

We have a side panel that lets user select the skills needed to be analysed for the strength of facts (ex: count of resources, number of trainings, ..) with a limit of 5 categories  that can be selected  maximum at any time. For every selection the browser should redraw the graph and render the graphical facts.

Problem :

offsetgrpcolchart
padding =0.2 , outer padding=0.5  for one category is slightly off from the tick despite using the same scale.

While the above combination for padding did work out well for 4 / 4+ categories it seems to fail as the categories reduce. Like here for one category the column group is slightly offset and demands re-calculation for the padding and outer padding.

quiteacceptable
Same formula seems to be working well here for 5 categories, padding =0.2 , outer padding =0.5

Change in the categories demands re-calculation of the outer padding. Rather even the padding can be adjusted and so can the bar width be , but that would mean we have too many moving parts here and hence an un-deterministic equation.

Lets keep the Range Interval, bar width , padding anchored to a constant value since changing them would mean we are changing the shape of diagram that may / may not be very appealing to the user.

Solution:

(2*op)+[(n-1)*p]*rb + (n*rb) =extent

  • op: outer padding
  • p: padding
  • rb: range band width
  • n: number of categories
  • extent: full usable width along with the geometry is rendered

Come to think of it , once you get your mind around this equation it would make sense to devise an equation to re-calculate the outer padding.

Snug fit the max case , reduce the moving parts further

Here is what I propose,  for the max number of categories  =5, lets snug fit without any outer padding, that gets ‘op’ out of the consideration to evaluate a ergonomic range band width.

Substituting op=0, n=5, extent = 770 is my case for the plot I have drawn.

rb = 132.7586… approximately ( to relate this to the linear diagram above, this is the step -padding , or the space for drawing the rectangle groups). I had chosen bar width = 20 with 5 subcategories again , I have 32.7586 to spare for each of groups.

Arriving at the equation for outer padding

op = ((extent – (n * rb) – ((n – 1) * padding * rb)) / 2)

Algebra 101 reveals the outer padding equation.

but wait you missed this , ain’t  it ? – the outer padding is percentage of range band width . We further correct our equation here

percentOp = op / rb

And that would give you the custom scale to define the outer padding for each of the categories count.

Full demo code available here

Whats your view ? was this any useful ?

Would love to hear from you.

 

Advertisements

3 thoughts on “D3.js Grouped column chart with selective categories

Add yours

  1. Honestly, it feels like you’ve got a LOT of JavaScript doing CSS’ job. Some things like the widths as a percentage of the range and heights for values certainly would need to be set, as would max-width on the ranges based on how many different rangesets are showing, but so much of what you are doing here could/should be unloaded on the markup and CSS and not handled from the scripting.

    More so if you go CSS3 and don’t care about pre IE9.

    You also seem to be working in pixels which is accessibility trash — remember, semi-fluid and elastic layout are your friend, even if they can be a bit of a pain to work with from JS; that’s why unloading as much as you can on the CSS is so important.

    Oh, and you might want to read up on WCAG colour contrasts, you’ve got a lot of text that isn’t up to accessibility minimums on this site.

    1. Yep , good spotting I might say on the code, I admit I wanted to escape adding a file to the gist. My point was to help those who were stuck wrestling d3.rangeRoundBand( ) outer padding values. Perhaps the title and the purpose of the post then mismatch ?

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Blog at WordPress.com.

Up ↑

%d bloggers like this: