how to color a qualitative gradient with R (using independent categories / multiple dimensions)
Asked Answered
P

2

2

sorry if i'm missing something fundamental about how colorRampPalette and brewer.pal work, but how can you create a qualitative color gradient based on multiple variables? my goal is to create a multidimensional qualitative gradient like the image shown below (red-to-green, red-to-yellow, red-to-blue and not red-to-yellow-to-green-to-blue).

enter image description here

minimal a reproducible example:

# example data set
mydata <- 
    data.frame(
        v = runif( 100 ) ,
        w = runif( 100 ) ,
        x = runif( 100 ) ,
        y = runif( 100 ) ,
        z = runif( 100 )
    )
# five columns of random values between zero and one

# use three columns with the `rgb` function to find
# the color between red, green, and blue using all three values
three.dimensions <- rgb( mydata$x , mydata$y , mydata$z )

# between zero and one, this gives black and white
plot( 0:1 , 0:1 , col = rgb( 0:1 , 0:1 , 0:1 ) , pch = 16 , cex = 3 )

# using the three sets of values, color on an rgb gradient
plot( rnorm( 100 ) , rnorm( 100 ) , col = three.dimensions , pch = 16 , cex = 3 )


# how is this multi-dimensionality
# supposed to be implemented in RColorBrewer?
library(RColorBrewer)

# create two colorRampPalette functions,
# for three- and five-category qualitative data
mypal3 <- brewer.pal( 3 , "Set1" )
mypal5 <- brewer.pal( 5 , "Set1" )

crp3 <- colorRampPalette( mypal3 )
crp5 <- colorRampPalette( mypal5 )


# this is just linear..  red, slowly to blue, slowly to green.
plot( rep( 1:10 , 10 ) , rep( 1:10 , each = 10 ) , col = crp3(100)[1:100] , pch = 16 , cex = 3 )

# how would i use RColorBrewer to get a three-way gradient
# with shades between red and green, as opposed to just red-to-blue-to-green?


# this is also linear across five colors.
plot( rep( 1:10 , 10 ) , rep( 1:10 , each = 10 ) , col = crp5(100)[1:100] , pch = 16 , cex = 3 )


# how would i use RColorBrewer to get a five-way gradient
# with shades between
    # red and blue
    # red and green
    # red and purple
    # red and orange
    # and every other combo, depending on the values in `mydata`?
Psychobiology answered 25/10, 2014 at 13:30 Comment(3)
I think, here you have the linear scale because that is precisely what you asked for. You can have separate linear scales, all beginning with red and transiting [independently] to blue, green e.t.c., BUT, that mapping must be defined in the data too i.e. there has to be a distinguishing attribute specifying what data goes to what scale.Disentangle
@Shekeine i don't really understand your comment. isn't that what columns v, u, x, y, and z tell you?Psychobiology
Actually, yes but at some point in the sample code, it sounds like how to composite RGB colours in colourbrewer is the main problem. The question is very clear though: Its only now that I understand that the plots you were doing in the example code were to illustrate what you wanted. .ill see if I can help..Disentangle
L
2

If I understand the question, you want to map different colour scales to different groups. Here's a possible strategy,

x <- seq(0,6*pi-0.01, length=100)
y <- sin(x)
i <- x%/%pi + 1 # groups in the data
d <- data.frame(x=x,y=y,i=i)

cols <- RColorBrewer::brewer.pal(length(unique(i)),"Set1")

library(plyr)

# for each group, map to a specific colorRamp
d2 <- ddply(d, "i", function(.d){
  id <- as.numeric(as.character(unique(.d$i)))
  pal <- colorRamp(c(cols[id], "white"), )
  cols <- pal(scales::rescale(.d$y))
  mutate(.d, col=rgb(cols[,1],cols[,2],cols[,3], maxColorValue = 255))
})


ggplot(d2, aes(x,y,colour=col,group=i))+
  geom_line(lwd=5) + scale_colour_identity() +
  theme_minimal()

same idea would apply for a map.

enter image description here

Liter answered 26/10, 2014 at 15:51 Comment(2)
i love this code but i'm not sure if it's really an answer to coloring the mydata object? each record in my data set has N different values, and the color should be decided based on the mix of them. so, for example, if you were mapping five non-english languages spoken in new york city ..every neighborhood of new york city has at least a few speakers of all five languages. but the colors need to be based on the relative mix of all five. your answer here (i think?) is still, at its core, a binary solution. in my data, every record is at least partially in every group. :)Psychobiology
i see, so you want to represent points in a N-dimensional space, in which each base vector is a colour ramp from white to red, or blue,... i.e. you want to generalise rgb() to more than 3 base vectors (4 with alpha). That sounds tricky, because you need to implement some kind of colour mixing function. There's colorspace::mixcolor, maybe that can help. Alternatively, use the standard layered mixing scheme of R graphics and superpose multiple (orthogonal) layers on top of each other with adequate transparency.Liter
P
0

i believe that something like this is the solution, although i can't believe there isn't a smarter way to do it.

https://mcmap.net/q/358804/-2d-color-gradient-plot-in-r

Psychobiology answered 26/10, 2014 at 13:7 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.