iJade
iJade

Reputation: 23791

d3js graph code showing y axes in different order for different data

Here is my d3js code

function ShowGraph(data) {
d3.selectAll('.axis').remove();
var vis = d3.select("#visualisation"),
    WIDTH = 500,
    HEIGHT = 500,
    MARGINS = {
        top: 20,
        right: 20,
        bottom: 20,
        left: 30
    },
    xRange = d3.scale.linear().range([MARGINS.left, WIDTH - MARGINS.right]).domain([d3.min(data, function (d) {
        return d.year;
    }),
    d3.max(data, function (d) {
        return d.year;
    })]),
    yRange = d3.scale.linear().range([HEIGHT - MARGINS.top, MARGINS.bottom]).domain([d3.min(data, function (d) {
        return d.count;
    }),
    d3.max(data, function (d) {
        return d.count;
    })]),
    xAxis = d3.svg.axis() // generate an axis
    .scale(xRange) // set the range of the axis
    .tickSize(5) // height of the ticks
    .tickSubdivide(true), // display ticks between text labels
    yAxis = d3.svg.axis() // generate an axis
    .scale(yRange) // set the range of the axis
    .tickSize(5) // width of the ticks
    .orient("left") // have the text labels on the left hand side
    .tickSubdivide(true); // display ticks between text labels
var transition = vis.transition().duration(1000).ease("exp-in-out");

transition.select(".x.axis").call(xAxis);
transition.select(".y.axis").call(yAxis);




vis.append("svg:g") // add a container for the axis
.attr("class", "x axis") // add some classes so we can style it
.attr("transform", "translate(0," + (HEIGHT - MARGINS.bottom) + ")") // move it into position
.call(xAxis); // finally, add the axis to the visualisation

vis.append("svg:g")
    .attr("class", "y axis")
    .attr("transform", "translate(" + (MARGINS.left) + ",0)")
    .call(yAxis);


var circles = vis.selectAll("circle").data(data)
circles.enter()
    .append("svg:circle")
    .attr("cx", function (d) {
    return xRange(d.year);
})
    .attr("cy", function (d) {
    return yRange(d.count);
})
    .style("fill", "red")

circles.transition().duration(1000)
    .attr("cx", function (d) {
    return xRange(d.year);
})
    .attr("cy", function (d) {
    return yRange(d.count);
})
    .attr("r", 10)

circles.exit()
    .transition().duration(1000)
    .attr("r", 10)
    .remove();

}

When the data used is

   [{"count": "202", "year": "1590"},
 {"count": "215", "year": "1592"},
 {"count": "179", "year": "1593"},
 {"count": "199", "year": "1594"},
 {"count": "134", "year": "1595"},
 {"count": "176", "year": "1596"},
 {"count": "172", "year": "1597"},
 {"count": "161", "year": "1598"},
 {"count": "199", "year": "1599"},
 {"count": "181", "year": "1600"},
 {"count": "157", "year": "1602"},
 {"count": "179", "year": "1603"},
 {"count": "150", "year": "1606"},
 {"count": "187", "year": "1607"},
 {"count": "133", "year": "1608"},
 {"count": "190", "year": "1609"},
 {"count": "175", "year": "1610"},
 {"count": "91", "year": "1611"},
 {"count": "150", "year": "1612"}
]

the y axis of the graph is as shown below(in asc order from top to bottom) enter image description here

When the data used is

    [{"count": "841", "year": "1590"},
 {"count": "848", "year": "1592"},
 {"count": "579", "year": "1593"},
 {"count": "753", "year": "1594"},
 {"count": "612", "year": "1595"},
 {"count": "740", "year": "1596"},
 {"count": "762", "year": "1597"},
 {"count": "894", "year": "1598"},
 {"count": "937", "year": "1599"},
 {"count": "995", "year": "1600"},
 {"count": "715", "year": "1602"},
 {"count": "786", "year": "1603"},
 {"count": "680", "year": "1606"},
 {"count": "942", "year": "1607"},
 {"count": "525", "year": "1608"},
 {"count": "779", "year": "1609"},
 {"count": "717", "year": "1610"},
 {"count": "421", "year": "1611"},
 {"count": "738", "year": "1612"}
]

the y axis of the graph is as shown below(in asc order from bottom to top) enter image description here

Can anyone point me out what may be the reason and how to correct this behaviour. update

another test data sample

[{"count": "357", "year": "1608"},
            {"count": "375", "year": "1611"},
            {"count": "506", "year": "1606"},
            {"count": "535", "year": "1610"},
            {"count": "551", "year": "1612"},
            {"count": "660", "year": "1597"},
            {"count": "679", "year": "1594"},
            {"count": "689", "year": "1598"},
            {"count": "873", "year": "1595"},
            {"count": "891", "year": "1592"},
            {"count": "990", "year": "1607"},
            {"count": "1031", "year": "1593"},
            {"count": "1038", "year": "1602"},
            {"count": "1064", "year": "1609"},
            {"count": "1264", "year": "1600"},
            {"count": "1357", "year": "1596"},
            {"count": "1616", "year": "1590"},
            {"count": "2299", "year": "1599"},
            {"count": "2559", "year": "1603"}]

Upvotes: 0

Views: 683

Answers (1)

jaime
jaime

Reputation: 42031

If you notice when rendering the first set of data, the y-axis doesn't look quite right. According the data the min count is 91 and max is 215, but the y-axis has 130 as the max.

This is because when building the scales and computing min and max, the values are compared as strings.

To fix it you need to either modify your data arrays to have numeric values where needed

[{ "count": 202, "year": 1590},
 { "count": 215, "year": 1592} /*....*/]

Or parse them into integers with parseInt when building the scales - and don't forget to pass the radix to parseInt.

If choosing the later, just modify your scales to this:

        /*....*/},
        xRange = d3.scale
                   .linear()
                   .domain([
                      d3.min(data, function(d){ return parseInt(d.year, 10);}),
                      d3.max(data, function(d){ return parseInt(d.year, 10);})
                    ])
                   .range([MARGINS.left, WIDTH - MARGINS.right]),
        yRange = d3.scale
                   .linear()
                   .domain([
                      d3.min(data, function(d){ return parseInt(d.count, 10);}),
                      d3.max(data, function(d){ return parseInt(d.count, 10);})
                    ])
                   .range([HEIGHT - MARGINS.top, MARGINS.bottom]),

Here's the JSFiddle: http://jsfiddle.net/jaimem/RPGPL/2/

Upvotes: 2

Related Questions