I have a very similar question as the one posted here: how to create multiline chart using dc.js
I am new to stackoverflow, which means that I am unable to add comments or I would have asked for additional information on that post. So, I apologize for any redundancy.
I have data structured like:
var data = {
{"id": 'id_value1', ..., "dates": {"name": {"d1":" 0-91","d2":" 92-182","d3":"183-273","d4":"274-364","d5":"365+"}, "value": {"v1":'A',"v2":'A',"v3":'C',"v4":'D',"v5":'B'}},
{"id": 'id_value2', ..., "dates": {"name": {"d1":" 0-91","d2":" 92-182","d3":"183-273","d4":"274-364","d5":"365+"}, "value": {"v1":'A',"v2":'B',"v3":'D',"v4":'C',"v5":'A'}},
...
{"id": 'id_valueN', ..., "dates": {"name": {"d1":" 0-91","d2":" 92-182","d3":"183-273","d4":"274-364","d5":"365+"}, "value": {"v1":'A',"v2":'A',"v3":'A',"v4":'-',"v5":'-'}}
}
I would like to create a bar graph that has "0-91","92-182","183-273","274-364","365+" as the x-axis variables. I also want to have it stacked such that each layer is a count for each individual letter (A,B,C,D). The data is stored such that d1 is the corresponding date for the v1 value, v2 is the value for date d2, and so on. In other words,
id ... 0-91 92-182 183-273 274-364 365+
id_value1 ... A A C D B
id_value2 ... A B D C A
...
id_valueN ... A A A - -
I would post a picture of what I want, but again (since I am so new) I am unable to. I know it would make more sense to see what I am asking for.
I have tried:
var ndx = crossfilter(data); // all data
var dim = ndx.dimension(function(d) {return d.id;});
var group1 = dim.group().reduceCount(function(d) {return d.dates.value.v1;});
var group2 = dim.group().reduceCount(function(d) {return d.dates.value.v2;});
var group3 = dim.group().reduceCount(function(d) {return d.dates.value.v3;});
var group4 = dim.group().reduceCount(function(d) {return d.dates.value.v4;});
var group5 = dim.group().reduceCount(function(d) {return d.dates.value.v5;});
var compositeChart = dc.compositeChart("#bar")
.width(1850).height(150)
.dimension(dim)
.group(group1)
.valueAccessor(function(d) {return d.value;})
.x(d3.scale.ordinal())
.xUnits(dc.units.ordinal)
.compose([
dc.barChart(compositeChart).group(group1).gap(10),
dc.barChart(compositeChart).group(group2).gap(10),
dc.barChart(compositeChart).group(group3).gap(10),
dc.barChart(compositeChart).group(group4).gap(10),
dc.barChart(compositeChart).group(group5).gap(10)
]);
But that doesn't work. The closest I have managed to get to what I want is to create 5 different graphs, one for each date. The following bit of code demonstrates this:
var chart1 = dc.barChart("#chart1");
var dim1 = ndx.dimension(function(d) {return d.dates.name.d1;});
var A1 = dim1.group().reduceSum(function(d) {if(d.dates.value.v1 === "A"){return +1;}else{return 0;}});
var B1 = dim1.group().reduceSum(function(d) {if(d.dates.value.v1 === "B"){return +1;}else{return 0;}});
var C1 = dim1.group().reduceSum(function(d) {if(d.dates.value.v1 === "C"){return +1;}else{return 0;}});
var D1 = dim1.group().reduceSum(function(d) {if(d.dates.value.v1 === "D"){return +1;}else{return 0;}});
var chart2 = dc.barChart("#chart2");
var dim2 = ndx.dimension(function(d) {return d.dates.name.d2;});
var A2 = dim2.group().reduceSum(function(d) {if(d.dates.value.v2 === "A"){return +1;}else{return +0;}});
var B2 = dim2.group().reduceSum(function(d) {if(d.dates.value.v2 === "B"){return +1;}else{return +0;}});
var C2 = dim2.group().reduceSum(function(d) {if(d.dates.value.v2 === "C"){return +1;}else{return +0;}});
var D2 = dim2.group().reduceSum(function(d) {if(d.dates.value.v2 === "D"){return +1;}else{return +0;}});
...
var chart5 = dc.barChart("#chart5");
var dim5 = ndx.dimension(function(d) {return d.dates.name.d5;});
var A5 = dim5.group().reduceSum(function(d) {if(d.dates.value.v5 === "A"){return +1;}else{return 0;}});
var B5 = dim5.group().reduceSum(function(d) {if(d.dates.value.v5 === "B"){return +1;}else{return 0;}});
var C5 = dim5.group().reduceSum(function(d) {if(d.dates.value.v5 === "C"){return +1;}else{return 0;}});
var D5 = dim5.group().reduceSum(function(d) {if(d.dates.value.v5 === "D"){return +1;}else{return 0;}});
chart1
.width(110).height(450)
.dimension(dim1)
.group(A5, "A's")
.stack(B5, "B's")
.stack(C5, "C's")
.stack(D5, "D's")
.y(d3.scale.linear().domain([minAll,maxAll]))
.x(d3.scale.ordinal())
.xUnits(dc.units.ordinal)
.elasticY(false)
.yAxisLabel("count")
.ordinalColors(["#008600","#80FF80","#FF80FF","#860086"])
.margins({top:20, left:60, right:10, bottom:120});
chart2
.width(50).height(450)
.dimension(dim2)
.group(A2, "A's")
.stack(B2, "B's")
.stack(C2, "C's")
.stack(D2, "D's")
.y(d3.scale.linear().domain([minAll,maxAll]))
.x(d3.scale.ordinal())
.xUnits(dc.units.ordinal)
.elasticY(false)
.ordinalColors(["#008600","#80FF80","#FF80FF","#860086"])
.margins({top:20, left:-1, right:10, bottom:120});
...
chart5
.width(50).height(450)
.dimension(dim5)
.group(A5, "A's")
.stack(B5, "B's")
.stack(C5, "C's")
.stack(D5, "D's")
.y(d3.scale.linear().domain([minAll,maxAll]))
.x(d3.scale.ordinal())
.xUnits(dc.units.ordinal)
.elasticY(false)
.ordinalColors(["#008600","#80FF80","#FF80FF","#860086"])
.margins({top:20, left:-1, right:10, bottom:120});
The problem with this is that these 5 graphs either won't have the same flexible y-axis or have the same non-flexible y-axis. I want to be able to click on other graphs in the dashboard with the result being that all graphs in the dashboard are updated to include/exclude the selection. This I don't have an issue with. I just can't create this stacked bar graph. I wanted to give reason to why I need the y-axis to be flexible.
I am using d3.js, dc.js, and crossfilter.js. The data is stored in a JSON file and is included in the html as a source file. Now that you have all the background information, I will ask my question.
How do I define the chart's dimension and group for this type of data to create the bar chart I desire?