Question

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>
Was it helpful?

Solution

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top