DivB
DivB

Reputation: 485

sort data for d3 stacked bar chart

I am trying to create d3 stacked bar chart. Data format is below

  var dataset = [{
    "effort": "initial",
        "co": [{
        "number": "123",
            "act_effort": 10
    },{
        "number": "456",
            "act_effort": 10
    }, {
        "number": "678",
            "act_effort": 0
    }]
    }, {
        "effort": "scope_creep",
           "co": [{
        "number": "456",
            "act_effort": 5
    }, {
        "number": "123",
            "act_effort": 0
    }, {
        "number": "678",
            "act_effort": 15
    }]
},{
    "effort": "qc_support",
           "co": [{
            "number": "456",
               "act_effort": 5
        },{
        "number": "678",
            "act_effort": 15
    }, {
        "number": "123",
            "act_effort": 5
    }]
    }, {
    "effort": "uat_support",
        "co": [{
        "number": "456",
            "act_effort": 0
    },  {
        "number": "678",
            "act_effort": 15
    },{
        "number": "123",
            "act_effort": 0
    }]
}];

As the data is not sorted there are breaks between bars in my stacked bar.

If I change the data into below it works

var dataset = [{
    "effort": "initial",
        "co": [{
        "number": "123",
            "act_effort": 10
    },{
        "number": "456",
            "act_effort": 10
    }, {
        "number": "678",
            "act_effort": 0
    }]
}, {
    "effort": "scope_creep",
        "co": [
            {
        "number": "123",
            "act_effort": 0
    },{
        "number": "456",
            "act_effort": 5
    }, {
        "number": "678",
            "act_effort": 15
    }]
},{
    "effort": "qc_support",
        "co": [{
        "number": "123",
            "act_effort": 5
    },{
        "number": "456",
            "act_effort": 5
    },{
        "number": "678",
            "act_effort": 15
    }]
},{
    "effort": "uat_support",
        "co": [{
        "number": "456",
            "act_effort": 0
    },  {
        "number": "678",
            "act_effort": 15
    },{
        "number": "123",
            "act_effort": 0
    }]
}];

Here is the working jsfiddle

I tried using d3.sort() function with no luck.

dataset = dataset.sort(function(a,b) { return d3.ascending(a.y, b.y);  }

Can some one suggest me how to achieve this? Thanks in advance.

Upvotes: 1

Views: 867

Answers (2)

user2010925
user2010925

Reputation:

I added a sort to your d.co.map, and it seems to have done the trick:

var dataset = dataset.map(function (d) {
    return d.co.map(function (o, i) {
        // Structure it so that your numeric
        // axis (the stacked amount) is y
        return {
            y: o.act_effort,
            x: o.number
        };
    }).sort(function(a, b) {
        return d3.ascending(parseInt(a.x), parseInt(b.x));
    });
});

Here is an updated working jsfiddle.

Upvotes: 0

Gilsha
Gilsha

Reputation: 14589

Try sorting the data as shown below.

var dataset = dataset.map(function (d) {
    var sortedData = d.co.sort(function(a,b){ return d3.ascending(a.number, b.number); });
    return sortedData.map(function (o, i) {         
        return {
            y: o.act_effort,
            x: o.number
        };
    });
});

var dataset = [{
    "effort": "initial",
        "co": [{
        "number": "123",
            "act_effort": 10
    },{
        "number": "456",
            "act_effort": 10
    }, {
        "number": "678",
            "act_effort": 0
    }]
    }, {
        "effort": "scope_creep",
           "co": [{
        "number": "456",
            "act_effort": 5
    }, {
        "number": "123",
            "act_effort": 0
    }, {
        "number": "678",
            "act_effort": 15
    }]
},{
    "effort": "qc_support",
           "co": [{
            "number": "456",
               "act_effort": 5
        },{
        "number": "678",
            "act_effort": 15
    }, {
        "number": "123",
            "act_effort": 5
    }]
    }, {
    "effort": "uat_support",
        "co": [{
        "number": "456",
            "act_effort": 0
    },  {
        "number": "678",
            "act_effort": 15
    },{
        "number": "123",
            "act_effort": 0
    }]
}];

var margin = {
    top: 50,
    right: 30,
    bottom: 50,
    left: 50
},

lagendPanel = {
    width: 180
},
width = 960 - margin.left - margin.right - lagendPanel.width,
    height = 500 - margin.top - margin.bottom;
var barPadding = 2;

d3.select("#main")
    .append("h4")
    .text("CO v/s Actual Effort Graph");
var effortTyp = dataset.map(function (d) {
    return d.effort;
});
var dataset = dataset.map(function (d) {
    var sortedData = d.co.sort(function(a,b){ return d3.ascending(a.number, b.number); });
    return sortedData.map(function (o, i) {
        // Structure it so that your numeric
        // axis (the stacked amount) is y
        return {
            y: o.act_effort,
            x: o.number
        };
    });
});
console.log(dataset);
var stack = d3.layout.stack();

stack(dataset);

var dataset = dataset.map(function (group) {
    return group.map(function (d) {
        // Invert the x and y values, and y0 becomes x0
        return {
            x: d.y,
            y: d.x,
            x0: d.y0

        };

    });

});
console.log(dataset);
var svg = d3.select("#main")
    .append('svg')
    .attr("width", width + (2 * margin.left) + margin.right + lagendPanel.width)
    .attr('height', height + margin.top + margin.bottom)
    .append('g')
    .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');

var xMax = d3.max(dataset, function (group) {
    return d3.max(group, function (d) {
        return d.x + d.x0;
    });
});

var xScale = d3.scale.linear()
    .domain([0, xMax])
    .range([0, width]);

var numbers = "";

numbers = dataset[0].map(function (d) {
    console.log(d.y);
    return d.y;
});
var yScale = d3.scale.ordinal()
    .domain(numbers)
    .rangeRoundBands([0, height], .1);


//Axis

var xAxis = d3.svg.axis()
    .scale(xScale)
    .orient('bottom'),

    yAxis = d3.svg.axis()
        .scale(yScale)
        .orient('left'),

    colours = d3.scale.category10();

var groups = svg.selectAll('g')
    .data(dataset)
    .enter()
    .append('g')
    .style('fill', function (d, i) {
    return colours(i);
}),

    rects = groups.selectAll('rect')
        .data(function (d) {
        return d;
    })
        .enter()
        .append('rect')
        .attr('x', function (d) {
        return xScale(d.x0);

    })
        .attr('y', function (d, i) {
        return yScale(d.y);
    })
        .attr('height', function (d) {
        return yScale.rangeBand();
    })
        .attr('width', function (d) {
        return xScale(d.x);
    });

svg.append('g')
    .attr('class', 'axis')
    .attr('transform', 'translate(0,' + height + ')')
    .call(xAxis);

svg.append('g')
    .attr('class', 'axis')
    .call(yAxis);

svg.append('g')
    .attr('class', 'axis')
    .call(yAxis);

svg.append('rect')
    .attr('fill', 'yellow')
    .attr('width', 160)
    .attr('height', 30 * dataset.length)
    .attr('x', width + margin.left)
    .attr('y', 0);

effortTyp.forEach(function (s, i) {
    svg.append('text')
        .attr('fill', 'black')
        .attr('x', width + margin.left + 8)
        .attr('y', i * 24 + 24)
        .text(s);
    svg.append('rect')
        .attr('fill', colours(i))
        .attr('width', 60)
        .attr('height', 20)
        .attr('x', width + margin.left + 90)
        .attr('y', i * 24 + 6);
});
<script type="text/javascript" src="http://d3js.org/d3.v3.min.js"></script>
<div id="main"></div>

Upvotes: 1

Related Questions