Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

D3 ordinal scale only returning extremes. Why isn't it interpolating between range and domain?

Tags:

svg

d3.js

I'm trying to use d3.scale.ordinal(). I am having an issue where the function only returns the minimum and maximum scale values.

I am trying to use d3.map() to construct the domain. Then I use an xScale function on the same value

My data looks like this:

key,to_state,value,type
Populate,District of Columbia,836,Populate
Populate,Maryland,1938,Populate
Populate,New Jersey,836,Populate
Populate,Pennsylvania,939,Populate
Populate,New York,3455,Populate

My scale function looks like this:

xScale = d3.scale.ordinal()
                .domain(d3.map(thedata, function(d){console.log(d.to_state); return d.to_state;}))
                .range([0, w - marginleft - marginright]);

My map selection looks like this. The Y and height values are all being calculated properly. Just the X is giving me trouble.

var thechart = chart.selectAll("div")
                .data(thedata)
                .enter()

console.log(xScale("New Jersey") + " " + xScale("Pennsylvania"));

thechart.append("rect").attr("x", function(d, i) {  
                        return xScale(d.to_state) + marginleft;
                    })
like image 310
Union find Avatar asked Jul 26 '14 23:07

Union find


1 Answers

An ordinal scale expects the same number of items in the .range array as there are in the .domain array. It is not like a linear scale which interpolates the in-between values when given the boundaries of the range as an array. Since you give only two items in the range, they are alternated as the return values for each value given in the domain.

If you want to have a different return value for each value in your domain, you need to provide the corresponding value in the range. Otherwise, if you just want to provide the boundaries of your range, and have the in-between values calculated for you, use .rangePoints() instead of .range().

HERE is an example that demonstrates the result of using both .range() and .rangePoints() when given 10 values in the domain and 2 values in the range.

To get this to work in your case, you will also want to take @AmeliaBR's suggestion of using Array.prototype.map rather than d3.map, and combine this with .rangePoints() to tween the values of your range.

xScale = d3.scale.ordinal()
  .domain(thedata.map(function(d){ return d.to_state;}) )
  .rangePoints([0, w - marginleft - marginright]);
like image 90
jshanley Avatar answered Oct 29 '22 08:10

jshanley