RGLSV
RGLSV

Reputation: 2058

Grouped multiple stacked bar chart

I'm trying to create a 'grouped stacked chart' (not sure if this is the right name) following this example, from bl.ocks.org. However my data comes from a json file, that's quite different from what the example provides, with the pattern: (please check jsfiddle, as its quite long)

"month": "november",
  "year": {
    "2015": {
      "item1": 2500,
      "item2": 3500,
      "item3": 4500
    },
    "2016": {
      "item1": 2300,
      "item2": 3200,
      "item3": 4100
    }
  }

The idea would be to be able to place side by side, 2 columns, representing the years, of the same month. Then inside those columns to be able to represent those item number stats.

I'm currently stuck as I'm not sure how to map that data the right way, as to achieve that result. I'm not interested on the colors, or legend / ticks and so on; only how to map that data correctly. Here's a graphical representation of the end result:

enter image description here

Any ideas or pointer are most welcomed.

Upvotes: 1

Views: 2923

Answers (1)

RGLSV
RGLSV

Reputation: 2058

Upon further investigation, the viable solution I found it to be to get that json object to 'look' like the data format provided in the stacked grouped chart example. This might not be the ideal way to get there, but it should get the job done.

What I did was to use a bunch of for .. in loops to build that object like in the initial example:

...cut-out version bellow...

itemLookup= data[0],
years = d3.keys(itemLookup.year),
items = d3.keys(itemLookup.year[years[0]]),
columnHeaders = [],
innerColumns = (function(){
  var result = {};
  for(var i = 0, ii = years.length; i<ii; i++){
    var holder = [];
    for(var j = 0, jj = items.length; j<jj; j++){
      columnHeaders.push(items[j]+'-'+years[i]);
      holder.push(items[j]+'-'+years[i]);
      result[years[i]] = holder;
    }
  }
  return result;
})()...

From here I was able to get to the initial example start point, where a object and an array as passed in as hard-coded, and used as a comparison guide that builds up the data; somewhere down the line in a foreach loop:

data.forEach(function(d, i){
  var tempData = {},
  curYear;
  tempData.monthName = d.month;

  //functionality to be implemented
  if(d.month === stripedPattern.monthName){
    chart
      .select('svg')
      .append('defs');
  }
  for(var key in d.year){
    if(curYear != key){
      curYear = key;
      tempData['totalValue-'+curYear] = 0;
    }
    var holder = d.year[key];
    for(var item in holder){
      tempData[item+'-'+key] = holder[item];
      tempData['totalValue-'+curYear] += parseInt(holder[item]);
    }
  }

  //this obj holds the correct data, similar to what the example provided
  dataRebuild.splice(i, 0, tempData);
});

And from here on, the idea stays the same as in the original example, as I got my data format to look like that data from the example, and be able to implement it.

Again if there are(most likely there are) some other more elegant solutions to reach to that endpoint, please share them around here.

Check out the 'working' demo here (work in progress)

Upvotes: 3

Related Questions