user1333781
user1333781

Reputation: 107

dc.js render bar chart

I'm trying to render a bar chart using the dc.js library. My csv dataset is formatted like so:

q, year, category, subcategory, total,
q1, 2010, x, xa, 200
q2, 2010, y, yb, 100
q3, 2010, x, xa, 300
q4, 2010, z, zb, 45
q1, 2010, x, xa, 80
q2, 2010, y, yb, 200
q3, 2010, x, xc, 301
q4, 2010, z, za, 205
q1, 2011, x, xa, 80
q2, 2011, y, yb, 200
q3, 2011, x, xc, 301
q4, 2011, z, za, 205

So far, I'm able to get a bar chart, but the actual data isn't rendered to the chart, also the scaling on the x-axis is off as well, since it should be according to years. I'm having difficulty appending the data to the graph. This is all that I've been able to get

enter image description here

I'm loading in the data through d3.csv as follows:

d3.csv("records.csv", function(csv) {
    var data = crossfilter(csv);

    var fiscalyear = data.dimension(function (d) {
        return d.year;
    });

    var spendGroup = fiscalyear.group().reduce(
        function(p,v) {
            return p.total += v.total;
        },
        function(p,v) {
            return p.total -= v.total;
        },
        function() {
            return  {totalSpend:0};
        }
    );

fiscalyearchart.width(600)
    .height(300)
    .margins({top: 10, right: 50, bottom: 30, left: 60})
    .dimension(fiscalyear)
    .group(spendGroup)
    .x(d3.scale.linear().domain([2010,2013]))
    .renderHorizontalGridLines(true)
    .centerBar(true)
    .elasticY(true)
    .brushOn(true);

    dc.renderAll();

});

Upvotes: 3

Views: 3681

Answers (1)

JRideout
JRideout

Reputation: 1635

The default valueAccessor determines the height of each column on Y axis. By default it assumes you it can use the value returned by your crossfilter group. So it expects something like:

console.log(group.all())

// [{key: 2010, value: 1},
//  {key: 2011, value: 2}]

But instead you are using a custom reduce function returning an object.

Your objects will look like this:

console.log(group.all())

// [{key: 2010, value: {total:NaN, totalSpend:0}},
//  {key: 2011, value: {total:NaN, totalSpend:0}}]

DC doesn't know what do with values like: {total:NaN, totalSpend:0}. You need to pass a valueAccessor to extract a numeric value like

chart.valueAccessor(function(d) {return d.totalSpend;});

Also, I presume you have a typo and really want to use p.totalSpend rather than p.total. But you could simplify further by just doing:

var spendGroup = fiscalyear.group().reduce(
    function(p,v) {
        return p += v.total;
    },
    function(p,v) {
        return p -= v.total;
    },
    function() {
        return 0;
    }
);

And this will return a .valueAccessor function dc can understand without customization. Even easier though, crossfilter already has a convenience function for this:

var spendGroup = fiscalyear.group().reduceSum(function(d) {return d.total;});

And DC has utility to create the callback:

var spendGroup = fiscalyear.group().reduceSum(dc.pluck('total'));

Upvotes: 7

Related Questions