tomtomtom
tomtomtom

Reputation: 1522

Color scale domain not displaying correctly

I am having some trouble with applying a colour scale on circles on a scatterplot.
What I did to set up the scale was:

var color = d3.scale.ordinal()
            .domain(d3.extent(dataset, function (d) { return parseFloat(d.Weight); }))
            .range(["#D6F5D6", "#ADEBAD", "#84E184", "#5BD75B","#32CD32"]);

And then apply the color to the circles with:

.attr("fill", function (d) { return color(d.Weight) }

But from the graph I can tell that the colours are not correct, in fact I see some values that are higher that have a lighter colour. I think the problem is that the values get read like strings, and in fact if I do the console log, the values that are not the min or max appear as strings, and I believe that this is the problem why I get wrong color values.
I tried also to set every d.Weight as a number in the domain, like so:

dataset.forEach(function (d) { d.Weight = +d.Weight; });

But it doesn't work either. Attached here's an image of what I'm getting: The X Axis is set to the Weight, so the colour of the points should be from lighter to darker going left to right, but it clearly isn't: enter image description here

Any help is appreciated, thanks!

EDIT Forgot to mention that i tried with scale.linear() but with it I get this result: enter image description here Just the first values get picked by the circles

Upvotes: 1

Views: 1278

Answers (1)

Lars Kotthoff
Lars Kotthoff

Reputation: 109232

Ordinal scales work differently from linear scales in that no interpolation between domain elements is done. To quote the documentation:

The first element in values will be mapped to the first element in the output range, the second domain value to the second range value, and so on.

This means that your input values are being mapped incorrectly, as you're only using min and max to set up the domain. For your purposes, you probably want a linear scale.

When using a linear scale, you'll have to tell D3 how to interpolate the values of the output range, e.g.

.range(["#D6F5D6", "#ADEBAD", "#84E184", "#5BD75B","#32CD32"])
.interpolate(d3.interpolateRgb);

Note that in this case, you also need to provide the same number of input values as output values:

Although linear scales typically have just two numeric values in their domain, you can specify more than two values for a polylinear scale. In this case, there must be an equivalent number of values in the output range.

In your case, it would be easiest to simply take the min and max and the two extreme colours.

Upvotes: 2

Related Questions