Skip to content Skip to sidebar Skip to footer

Mapping In D3 Ordinal Scales

I am using D3's ordinal scale, to map numbers to color. I have used this: color = d3.scale.ordinal().range(['#1f77b4', '#ff7f0e', '#2ca02c', '#d62728', '#9467bd', '#8c564b', '#e3

Solution 1:

The domain isn't quite right:

> color.domain()
[0, 6, 1, 0.5]

For each value in an ordinal scale's range, there should to be a matching value in the domain.

Instead of setting the domain to [0,6], it should be [0, 1, 2, 3, 4, 5, 6]:

color = d3.scale.ordinal()
          .range(["#1f77b4", "#ff7f0e", "#2ca02c", "#d62728", "#9467bd", "#8c564b", "#e377c2"])
          .domain(d3.range(0,7));

Checking to make sure everything works after updating color:

> d3.range(0,7).forEach(function(d){ console.log(color(d)); })
#1f77b4#ff7f0e#2ca02c#d62728#9467bd#8c564b#e377c2

Solution 2:

This is expected as there are only 2 explicitly defined values in your domain. So the first value of 0 is assigned to the first color of #1f77b4, the second value of 6 is assigned to the second color,#ff7f0e, and the remainders are inferred after they are sorted internally as strings. You need to define the domain explicitly for predictable behavior. For example,

color = d3.scale.ordinal()
  .range(["#1f77b4", "#ff7f0e", "#2ca02c", "#d62728", "#9467bd", "#8c564b", "#e377c2"])
  .domain([0,1,2,3,4,5,6]);

console.log(color(0),color(1),color(2),color(3),color(4),color(5),color(6));

As the documentation states

Setting the domain on an ordinal scale is optional. If no domain is set, each unique value that is passed to the scale function will be assigned a new value from the output range; in other words, the domain will be inferred implicitly from usage. However, it is a good idea to assign the ordinal scale's domain to ensure deterministic behavior, as inferring the domain from usage will be dependent on ordering.

Post a Comment for "Mapping In D3 Ordinal Scales"