d3 / d3-color

Color spaces! RGB, HSL, Cubehelix, CIELAB, and more.
https://d3js.org/d3-color
ISC License
401 stars 91 forks source link

Automatically pick N distinct colors? #11

Closed curran closed 9 years ago

curran commented 9 years ago

This is not an "issue" per se with d3-color, but just an idea / research problem that you may want to consider.

I always thought it would be great to have an algorithm that automagically picks N distinct colors that are as far apart perceptually as possible, for representing categorical values. Perhaps d3.scale.category20() and friends fills this need currently in practice, but I feel like there should be an algorithm for this.

Here is a first attempt at such an algorithm that places points on a circle in LAB space (L is fixed, and the points vary only in (A, B), so they have equal luminance but different hue) http://bl.ocks.org/curran/dd73d3d8925cdf50df86.

Perhaps a better solution would be use Mitchell’s best-candidate algorithm for generating a Poisson-disc distribution in a limited region of (A, B) color space (perhaps a circle?), where the user could specify as input a fixed L value and the desired number of distinct colors. Also Lloyd relaxation might be another nice way to do this.

The API documentation might look something like this:


color.distinct(n, [L])

Returns an array of n colors that are perceptually distinct. If L is specified, it controls the fixed L value in LAB color space that the algorithm uses. If L is not specified, it defaults to 50.


Just an idea.

It's great to see all this activity on the new D3, excited to try it out!

mbostock commented 9 years ago

The thing is, you’re never going to want more than 10 hues for categorical colors.* You might get more than that if you vary lightness as well, such as category20 which pairs light and dark, and category20b and category20c which have four shades per hue. But then you have to be careful about the semantic association caused by the grouping.

So, I find that in practice a handful of hand-picked hues are going to outperform automatic selection. I can see that sometimes it’s nice to start with a different set of hues if you want to match a particular aesthetic. But it’s rare that you want to pick equidistant hues in HCL or some such, since the hand-picked ones are often going to look better and perform at least as well.

*Just like you’re never going to want more than 640KB.

curran commented 9 years ago

Thank you for your thoughts on this. You make very good points.

I think I'll close this issue then, as it seems like the idea of automatically picking N colors is more of an academic curiosity than a practical need.

armandidandeh commented 6 years ago

@mbostock @curran As I have run into the need for more than 10, I decided to comment on this issue.

Here is the case: I need 20 colors for 20 topics that were created by LDA. I have limited my soft topics to 20 because I wanted to use 20 or 20c as my scale. Now here is my problem: with 20 topics:

image

And with 2 topics: screenshot-2018-2-13 varsity

If I had more than 20 colors, I would certainly upgrade the limit to 25 or 30.

Any thoughts as to what extent can we actually have distinct colors? I am creating a custom scale but your feedback would be much appreciated.

curran commented 6 years ago

@armandidandeh I did something rather crazy and generated a color scale with something like 200 different hues, like this:

export default scaleOrdinal()
  .domain(allCountries)
  .range(allCountries.map((country, i) => {
    const t = i / allCountries.length;
    return hcl(t * 360, 50, 70);
  }));

From https://github.com/unhcr/dataviz-streamgraph-explorer/blob/master/src/colorScale.js

It worked OK, but probably you can't differentiate all of them.

image

Tamara Munzner says a good rule of thumb is not more than 12 colors, from Visualization Analysis and Design.

armandidandeh commented 6 years ago

@curran thanks for the input. Agreed but 12 is not realistic. I once did something very similar to your code using a hypercube idea a few years back but as you said, not very practical as well.

mohabisback commented 2 years ago

after a bit of thinking the algorism should be considering colors as a simi cone its topmost point is black its base circle is hue the most bottom point of the cup is white the diameter of the hue circle equals the distance from black to white

... when ever you come near the base center the color becomes lighter when ever you move towards the top of the cone the color becomes darker

the algorism should pick up n points in this simi cone, farest from each other ... in the beginnig it will be easy, picking the top most point(black), and some of the base points ... but after a while, you will need to go upwards to distripute fine your colors using the whole body of, colors like black, navy, dark red, maroon and so on ... this can be done manualy from the pie i learned from you, and i added to it a tooltip