3

I can't grok the docs on d3's ordinal scales. The way I read it (and the way it works for linear scales, I feel I should be able to proceed like this:

color = d3.scale.ordinal();
color.domain([0, 100]);      // Input is any percentage point 0-100
color.range([                // Output is a scale of colors from "bad" to "good"
  'red','orange','blue','green'
]);

This doesn't give me the results I expect:

color(0); // "red". Ok, that makes sense
color(1); // "blue". Huh? This should be "red"
color(100); // "orange". Really? I'm confused. What's the range?
color.range(); //["red", "orange", "blue", "green"]. That looks right...
color.domain(); // [0,1,100]. Um...

It looks like it's treating inputs as discrete categorical values when I want to treat them like numbers.

SimplGy
  • 20,079
  • 15
  • 107
  • 144
  • Well that's what the ordinal scales do -- see the docs. In particular you should have one domain element per range element. You probably want a linear scale instead. – Lars Kotthoff Apr 19 '15 at 02:46

2 Answers2

4

The correct approach for mapping a range of numbers to discrete outputs is to use quantize. The difference wasn't clear to me and ordinal seemed intuitive. Figured it out now.

A working solution looks like this:

color = d3.scale.quantize();
color.domain([0, 100]);
color.range([
  'red','orange','blue','green'
]);

color(0);  // "red"
color(1);  // "red"
color(99); // "green"

These links here helpful in figuring this out:

Community
  • 1
  • 1
SimplGy
  • 20,079
  • 15
  • 107
  • 144
2

The approach to this is not exactly how it works. The domain you listed will point to 2 specific values in the range, the 2 first values - red and orange. Any other value that you add to the domain via color(n); will extend the domain array, eg. 1 is considered the 3rd index, therefore it is assigned the 3rd item in the range, if you were to call another item with color(n) you would get the 4th index. That is how the range method works.

frazras
  • 5,928
  • 4
  • 30
  • 40