santosh santosh - 4 months ago 20
Javascript Question

dc.js: stacked barchart cant display

I'm making a stacked barchart using the Dimensional Charting javascript library dc.js, which is based on d3 and crossfilter. I am new in dc.js library. I am trying to display the stacked barchart using a csv file. I can't understand how to create a stacked barchart following the csv format.

State_Name Age_19_Under Age_19_64 Age_65_84
AL 26.9 62.3 9.8
AL 23.5 60.3 14.5
NW 24.3 62.5 11.6
NW 24.6 63.3 10.9
BR 24.5 62.1 12.1
BR 24.7 63.2 10
GH 25.6 58.5 13.6
GH 24.1 61.6 12.7
KS 24.8 59.5 13.5


i am trying following code:

<script type="text/javascript">
var stacked = dc.barChart("#chart");
d3.csv("{% static 'sampledata/healthdata111.csv' %}", function(error, experiments) {

var ndx = crossfilter(experiments);
var all = ndx.groupAll();

var stateDim=ndx.dimension(function (d){
return d.State_Name;
});

var eventsByDate = stateDim.group().reduce(
function (p, v) {
p.Age_19_Under += v.Age_19_Under;
p.Age_19_64 += v.Age_19_64;
p.Age_65_84 += v.Age_65_84;
return p;
},
function (p, v) {
p.Age_19_Under -= v.Age_19_Under;
p.Age_19_64 -= v.Age_19_64;
p.Age_65_84 -= v.Age_65_84;
return p;
},
function () {
return {
Age_19_Under: 0,
Age_19_64: 0,
Age_65_84: 0
};
}
);

var colorRenderlet = function (chart) {
chart.selectAll("rect.bar")
.on("click", function (d) {
function setAttr(selection, keyName) {
selection.style("fill", function (d) {
if (d[keyName] == "Age_19_Under") return "#63D3FF";
else if (d[keyName] == "Age_19_64") return "#FF548F";
else if (d[keyName] == "Age_65_84") return "#9061C2";
});
}
setAttr(_chart.selectAll("g.stack").selectAll("rect.bar"), "layer");
setAttr(_chart.selectAll("g.dc-legend-item").selectAll("rect"), "name")
});
};

stacked
.margins({top: 50, right: 20, left: 50, bottom: 50})
.width(500)
.height(200)
.gap(50)
.dimension(stateDim)
.group(eventsByDate, "Age_19_Under")
.valueAccessor(function (d) {
return d.value.Age_19_Under;
})
.stack(eventsByDate, "Age_19_64", function (d) {
return d.value.Age_19_64;
})
.stack(eventsByDate, "Age_65_84", function (d) {
return d.value.Age_65_84;
})
.x(d3.time.scale().domain([0,5000]))
.xUnits(d3.time.days)
.centerBar(true)
.elasticY(true)
.brushOn(false)
.renderlet(colorRenderlet);
// .legend(dc.legend().x(100).y(0).itemHeight(13).gap(5));

dc.renderAll();

});

</script>

Answer

I'm not sure what kind of interaction you're trying implement with the event handler, so setting that aside, I think you can simplify things if you just create a separate group for each age category.

var experiments = [
    { State_Name: "AL", Age_19_Under: 26.9, Age_19_64: 62.3, Age_65_84: 9.8, Age_85_and_Over: 0.9 },
    { State_Name: "AL", Age_19_Under: 23.5, Age_19_64: 60.3, Age_65_84: 14.5, Age_85_and_Over: 1.8 },
    { State_Name: "NW", Age_19_Under: 24.3, Age_19_64: 62.5, Age_65_84: 11.6, Age_85_and_Over: 1.6 },
    { State_Name: "NW", Age_19_Under: 24.6, Age_19_64: 63.3, Age_65_84: 10.9, Age_85_and_Over: 1.2 },
    { State_Name: "BR", Age_19_Under: 24.5, Age_19_64: 62.1, Age_65_84: 12.1, Age_85_and_Over: 1.3 },
    { State_Name: "BR", Age_19_Under: 24.7, Age_19_64: 63.2, Age_65_84: 10.0, Age_85_and_Over: 2.2 },
    { State_Name: "GH", Age_19_Under: 25.6, Age_19_64: 58.5, Age_65_84: 13.6, Age_85_and_Over: 2.4 },
    { State_Name: "GH", Age_19_Under: 24.1, Age_19_64: 61.6, Age_65_84: 12.7, Age_85_and_Over: 1.5 },
    { State_Name: "KS", Age_19_Under: 24.8, Age_19_64: 59.5, Age_65_84: 13.5, Age_85_and_Over: 2.2 },
];

var ndx = crossfilter(experiments);

var stateDim = ndx.dimension(function (d) { return d.State_Name; });
var age19UnderGroup = stateDim.group().reduceSum(function (d) { return d.Age_19_Under; });
var age19To64Group = stateDim.group().reduceSum(function (d) { return d.Age_19_64; });
var age65To84Group = stateDim.group().reduceSum(function (d) { return d.Age_65_84; });
var age85AndOverGroup = stateDim.group().reduceSum(function (d) { return d.Age_85_and_Over; });

var stackedBarChart = dc.barChart("#chart-row-Poverty1");

stackedBarChart
    .dimension(stateDim)
    .group(age19UnderGroup)
    .x(d3.scale.ordinal())
    .xUnits(dc.units.ordinal)
    .stack(age19To64Group)
    .stack(age65To84Group)
    .stack(age85AndOverGroup)
;

dc.renderAll();

Note that if you do it this way you have to assign one of your four groups to the base chart to get things started. The three remaining charts then just stack on top of it.

Comments