runtimeZero
runtimeZero

Reputation: 28116

Using Ordinal axis to render scatter plot in D3

My data looks as below:

var sampleData = [{ "x": 'GOOG', "y": 5 }, { "x": 'FB', "y": 20 }, { "x": 'MSFT', "y": 10 }, { "x": 'EBAY', "y": 40 }, { "x": 'AMZN', "y": 5 }, { "x": 'AAPL', "y": 60 }];

x axis represents the stock name and y axis represents the number of stocks.

I am trying to represent the same using scatter plot where x axis will be ordinal (representing stock name) and y-axis will be number of stocks.

My code is below. Nothing gets rendered as such.

var vis = d3.select("#svgVisualize");

  var yMax = d3.max(sampleData, function(point) {return point.y;});

  //step 1 : scale the data

  var xange = d3.scale.ordinal();
  var yRange = d3.scale.linear().range([400, 40]).domain([0,yMax]);


  //step 2: scale the axis
  var xAxis = d3.svg.axis().scale(xRange);
  var yAxis = d3.svg.axis().scale(yRange).orient("left");

  //Step3: append the x and y axis
  vis.append('svg:g').call(xAxis).attr("transform", "translate(0,400)");
  vis.append('svg:g').call(yAxis).attr("transform", "translate(40,0)");

  var circles = vis.selectAll("circle").data(sampleData);

  circles
    .enter()
    .insert("circle")
    .attr("cx", function(d) { return xRange (d.x); })
    .attr("cy", function(d) { return xRange (d.x); })
    .attr("r", 10)
    .style("fill", "red");

Plnkr available here:

http://plnkr.co/edit/5v76uKi5wDK65H2GGqVn

Upvotes: 2

Views: 1056

Answers (1)

Henry S
Henry S

Reputation: 3112

I made a couple of changes in this updated Plunk: http://plnkr.co/edit/YDUxLQWg5tiIBN5eBHkf (although there's still some axis positioning to sort out).

First, the console was showing an error: "Uncaught ReferenceError: xRange is not defined". That's just a typo, change:

var xange = d3.scale.ordinal();

to

var xRange = d3.scale.ordinal();

Next, even for ordinal scales you need to define the range and domain. I added:

var xRange = d3.scale.ordinal()
    .domain(sampleData.map(function(d) { return d.x; }))
    .rangePoints([0, 400]);

The domain is all x values from the data, and these are evenly spaced along the 400px axis using rangePoints

Finally I changed how your circles' dy attribute was being calculated (was using x values, presume a copy-paste error):

.attr("cy", function(d) { return xRange(d.x); })

to

.attr("cy", function(d) { return yRange(d.y); })

Upvotes: 1

Related Questions