[R] Palettes {grDevices} - wrong number of colors returned?

Duncan Murdoch murdoch@dunc@n @end|ng |rom gm@||@com
Thu Feb 23 12:04:05 CET 2023


On 23/02/2023 4:36 a.m., Sigbert Klinke wrote:
> Hi,
> 
> I would have expected that I get always 3 colors as result which is not
> true:
> 
> hcl.colors(3, alpha=c(0, 0.5, 1))     # 3 colors
> 
> rainbow(3, alpha=c(0, 0.5, 1))        # 3 colors
> 
> heat.colors(3, alpha=c(0, 0.5, 1))    # 3 colors
> 
> terrain.colors(3, alpha=c(0, 0.5, 1)) # 6 colors
> 
> cm.colors(3, alpha=c(0, 0.5, 1))      # 6 colors
> 
> topo.colors(3, alpha=c(0, 0.5, 1))    # 9 colors
> 
> R-Version and platform:
> R version 4.2.2 Patched (2022-11-10 r83330) -- "Innocent and Trusting"
> 
> Copyright (C) 2022 The R Foundation for Statistical Computing
> 
> Platform: x86_64-pc-linux-gnu (64-bit)
> 
> Bug or feature?

Looks like a bug to me, they should all be length 3.  The reason it 
happens in terrain.colors (I didn't look at the others) is that it 
breaks the range into two parts, and relies on the number of values of 
the parameters in each part to get the length, but passes the full alpha 
vector in:

terrain.colors <- function (n, alpha, rev = FALSE)
{
     if ((n <- as.integer(n[1L])) > 0) {
	k <- n%/%2
	h <- c(4/12, 2/12, 0/12)
	s <- c(1, 1, 0)
	v <- c(0.65, 0.9, 0.95)
	cols <- c(hsv(h = seq.int(h[1L], h[2L], length.out = k),
                       s = seq.int(s[1L], s[2L], length.out = k),
                       v = seq.int(v[1L], v[2L], length.out = k), alpha 
= alpha),
                   hsv(h = seq.int(h[2L], h[3L], length.out = n - k + 
1)[-1L],
                       s = seq.int(s[2L], s[3L], length.out = n - k + 
1)[-1L],
                       v = seq.int(v[2L], v[3L], length.out = n - k + 
1)[-1L],
                       alpha = alpha))
         if(rev) rev(cols) else cols
     } else character()
}


A bug fix would be to recycle alpha to the right length and only pass in 
portions of it, e.g.

terrain.colors <- function (n, alpha, rev = FALSE)
{
     if ((n <- as.integer(n[1L])) > 0) {
         alpha <- rep_len(alpha, length.out = n)
	k <- n%/%2
	h <- c(4/12, 2/12, 0/12)
	s <- c(1, 1, 0)
	v <- c(0.65, 0.9, 0.95)
	cols <- c(hsv(h = seq.int(h[1L], h[2L], length.out = k),
                       s = seq.int(s[1L], s[2L], length.out = k),
                       v = seq.int(v[1L], v[2L], length.out = k), alpha 
= alpha[seq_len(k)]),
                   hsv(h = seq.int(h[2L], h[3L], length.out = n - k + 
1)[-1L],
                       s = seq.int(s[2L], s[3L], length.out = n - k + 
1)[-1L],
                       v = seq.int(v[2L], v[3L], length.out = n - k + 
1)[-1L],
                       alpha = alpha[seq_len(n - k) + k]))
         if(rev) rev(cols) else cols
     } else character()
}

I'd guess the same sort of approach would fix cm.colors and topo.colors.

Duncan Murdoch



More information about the R-help mailing list