Hi All, I am plotting a scatterplot of 21 populations, and I am using rainbow(21)[pops.col] to generate 21 colours for the plot (which works). Maybe it is because I can really process few colours at a time, but the differences between the colours are not as strong as I?d like. I can specify start and end for rainbow(), but if anything that looks worse if I do not just stick to 0 and 1. Is there a way of getting a set of 21 colours that maximises the differences between them? I could pick them by hand, but that is about 15 colours more than I know (I have a detailed colourchart, but the visual differences between ?skyblue? and ?slategrey? elude me when plotted as dots on a plot). Cheers F -- Federico Calboli LBEG - Laboratory of Biodiversity and Evolutionary Genomics Charles Deberiotstraat 32 box 2439 3000 Leuven +32 16 32 87 67
You could look at combning a number of palettes from the RColorBrewer package to get the palette length you want. S Ellison> -----Original Message----- > From: R-help [mailto:r-help-bounces at r-project.org] On Behalf Of Federico > Calboli > Sent: 11 September 2018 08:35 > To: r-help at r-project.org > Subject: [R] getting 21 very different colours > > Hi All, > > I am plotting a scatterplot of 21 populations, and I am using > rainbow(21)[pops.col] to generate 21 colours for the plot (which works). > Maybe it is because I can really process few colours at a time, but the > differences between the colours are not as strong as I?d like. I can specify > start and end for rainbow(), but if anything that looks worse if I do not just > stick to 0 and 1. > > Is there a way of getting a set of 21 colours that maximises the differences > between them? > > I could pick them by hand, but that is about 15 colours more than I know (I > have a detailed colourchart, but the visual differences between ?skyblue? and > ?slategrey? elude me when plotted as dots on a plot). > > Cheers > > F > -- > Federico Calboli > LBEG - Laboratory of Biodiversity and Evolutionary Genomics > Charles Deberiotstraat 32 box 2439 > 3000 Leuven > +32 16 32 87 67 > > > > > > ______________________________________________ > R-help at r-project.org mailing list -- To UNSUBSCRIBE and more, see > https://stat.ethz.ch/mailman/listinfo/r-help > PLEASE do read the posting guide http://www.R-project.org/posting- > guide.html > and provide commented, minimal, self-contained, reproducible code.******************************************************************* This email and any attachments are confidential. Any use, copying or disclosure other than by the intended recipient is unauthorised. If you have received this message in error, please notify the sender immediately via +44(0)20 8943 7000 or notify postmaster at lgcgroup.com and delete this message and any copies from your computer and network. LGC Limited. Registered in England 2991879. Registered office: Queens Road, Teddington, Middlesex, TW11 0LY, UK
On Tue, 11 Sep 2018 07:34:51 +0000 Federico Calboli <federico.calboli at kuleuven.be> wrote:> Is there a way of getting a set of 21 colours that maximises the > differences between them?In my limited experience, getting even 10 colours to look different enough is a serious undertaking. Take a look at RColorBrewer: display.brewer.all(n, "qual") stops offering palettes for n>12. When I needed a 10-colour categorical/qualitative palette, I opted for brute force approach of maximising the minimal distance between points in HCL colourspace, although later my colleague told me that I just needed an existing algorithm to place the points uniformly. It has to be HCL and not RGB because HCL signifies the way people perceive different colours while RGB is only a good representation hardware-wise. Here is my code; the usual disclaimers about stuff written between 1 and 3 AM apply: # -------------------------8<--------------------------- require(nloptr) h <- c(0,360) c <- c(0,137) # see the warning about fixup in `?hcl`: not all HCL points are representable in RGB # NOTE: depending on your plot background, you may have to change at least luminance range l <- c(30,90) npoints <- 24 # I had only 10 here pts <- matrix(ncol=3, nrow=npoints, dimnames=list(NULL, c("h","c","l"))) pts[,"h"] <- runif(npoints, min=h[1], max=h[2]) pts[,"c"] <- runif(npoints, min=c[1], max=c[2]) pts[,"l"] <- runif(npoints, min=l[1], max=l[2]) lb <- cbind(h=rep(h[1],npoints), c=rep(c[1],npoints), l=rep(l[1],npoints)) ub <- cbind(h=rep(h[2],npoints), c=rep(c[2],npoints), l=rep(l[2],npoints)) obj <- function(x) { pts[,c("h","c","l")] <- x # somehow the best results were achieved by calculating Euclidean distance from cylindrical coordinates pts <- cbind(pts[,"c"]*sin(pts[,'h']/360*2*pi), pts[,'c']*cos(pts[,'h']/360*2*pi), pts[,'l']) d <- as.matrix(dist(pts)) diag(d) <- NA # maximise minimal distance <=> minimize negative of minimal distance -min(d, na.rm=T) } # the stopping criterion is a bit lame, but the objective function here is very hard to minimize # 1e6 iterations take a few minutes on a relatively modern desktop sol <- nloptr(as.vector(pts), obj, lb=as.vector(lb), ub=as.vector(ub), opts=list(algorithm="NLOPT_GN_CRS2_LM", maxeval=1e6)) pts[,c("h","c",'l')] <- sol$solution plot(pts[,"c"] * sin(pts[,"h"]/360*2*pi), pts[,"c"] * cos(pts[,"h"]/360*2*pi), col=hcl(pts[,"h"], pts[,"c"], l), pch=19, cex=2) # -------------------------8<--------------------------- I couldn't get my code to produce 24 acceptably different colours, but maybe you will succeed with a similar approach. -- Best regards, Ivan
On 11/09/2018 3:34 AM, Federico Calboli wrote:> Hi All, > > I am plotting a scatterplot of 21 populations, and I am using rainbow(21)[pops.col] to generate 21 colours for the plot (which works). Maybe it is because I can really process few colours at a time, but the differences between the colours are not as strong as I?d like. I can specify start and end for rainbow(), but if anything that looks worse if I do not just stick to 0 and 1. > > Is there a way of getting a set of 21 colours that maximises the differences between them?The LAB and LUV color spaces (in the colorspace package) attempt to map perceptual differences to equal distances. You could try using a grid of points in one of those spaces, but not all triples are valid. However, 21 colours is probably too many for your purpose. If you really want to distinguish 21 groups, you're likely going to have to use other characteristics as well, such as the symbol. You could plot 21 different letters in 5 different colours and it might work, but it's not going to be easy for viewers. Duncan Murdoch> > I could pick them by hand, but that is about 15 colours more than I know (I have a detailed colourchart, but the visual differences between ?skyblue? and ?slategrey? elude me when plotted as dots on a plot). > > Cheers > > F > -- > Federico Calboli > LBEG - Laboratory of Biodiversity and Evolutionary Genomics > Charles Deberiotstraat 32 box 2439 > 3000 Leuven > +32 16 32 87 67 > > > > > > ______________________________________________ > R-help at r-project.org mailing list -- To UNSUBSCRIBE and more, see > https://stat.ethz.ch/mailman/listinfo/r-help > PLEASE do read the posting guide http://www.R-project.org/posting-guide.html > and provide commented, minimal, self-contained, reproducible code. >