Search code examples
rggplot2plotlyggplotly

Conditional color for geom_line


I would like to get a single line passing through given points and having specified colors for values which are within specified intervals. But I can only get multiple lines of the specified colors rather than a single line which would change colors on its subintervals.

The reproducible example is as follows:

require(ggplot2)
require(plotly)

vectX <- c(-5,-4.5,-3.2,-2.1,-0.8,0.1,1.3,2.7,3.6,4.4,5)
vectY <- c(-2.3,1.4,2.7,0.3,-0.4,1.5,3.9,2.4,0.5,-1.2,1.4)

requestedQuantilesZscores <-  c(0.0,0.25,0.5,0.75,1.0)
zScores <- base::scale(vectY, center = TRUE, scale = TRUE)
quantilesZscore <- stats::quantile(zScores, requestedQuantilesZscores, na.rm = TRUE)

theDataFrame <- base::data.frame(theX = vectX, theY = vectY, theZ = zScores)

valuesColor <- c('green','red','blue','yellow','orange')
theDataFrame$conditionalColor <- ifelse(theDataFrame$theZ > quantilesZscore[[4]], valuesColor[[1]] ,
      ifelse(theDataFrame$theZ > quantilesZscore[[3]] & theDataFrame$theZ <= quantilesZscore[[4]], valuesColor[[2]],
        ifelse(theDataFrame$theZ > quantilesZscore[[2]] & theDataFrame$theZ <= quantilesZscore[[3]], valuesColor[[3]],
          ifelse(theDataFrame$theZ <= quantilesZscore[[2]], valuesColor[[4]], valuesColor[[5]]))))

theGGplotLine <- ggplot(theDataFrame) +
  geom_line(aes(x = theX, y = theY, color = conditionalColor)) +
  xlab('X') + ylab('Y') +
  scale_colour_manual(values = valuesColor) +
  theme(legend.position='none')

theGGplotLine

(plotly::ggplotly(theGGplotLine))

Solution

  • If I understand correctly what you want, all you need is to add a different grouping into your ggplot code

    theGGplotLine <- ggplot(theDataFrame) +
      geom_line(aes(x = theX, y = theY, color = conditionalColor, group = 1)) +
      xlab('X') + ylab('Y') +
      scale_colour_manual(values = valuesColor) +
      theme(legend.position='none')
    

    This gives one line with all points connected, but the colour is dependent on the conditionalColor column. Grouping like this could also be based on a separate column if necessary