How to get multiple colors for geom_line, determined by a specific value

I have the following data frame that I would like to build. I was wondering if it is possible to color the parts of the lines connecting my original variable (stackOne $ y) in a different color, depending on whether it is less than a certain value or not. For example, I would like the parts of the lines falling below 2.2 to be red.

id<-rep(c(1,2,3),each=3) y<-rnorm(9,2,1) x<-rep(c(1,2,3),3) stackOne<-data.frame(cbind(id,y,x)) p<-ggplot(stackOne,aes(x=x,y=y)) + geom_point()+ geom_line(aes(group=id)) p 

Thanks!

+4
source share
1 answer

You have at least a couple of options. The first is quite simple, general (in that it is not limited to direct segments) and accurate, but uses base plot , not ggplot . The second one uses ggplot , but a little more complicated and the color transition will not be 100% accurate (but close enough if you specify the appropriate resolution ... read on).

base:

If you want to use the base build functions rather than ggplot , you can crop the build area above the threshold (2.2), and then draw the segments in the preferred color and then copy to the area below the threshold and the graph again in red. While the first clip is completely unnecessary, it prevents you from dragging and dropping different colors, which may look a little annoying.

 threshold <- 2.2 set.seed(123) stackOne=data.frame(id=rep(c(1,2,3),each=3), y=rnorm(9,2,1), x=rep(c(1,2,3),3)) # create a second df to hold segment data d <- stackOne d$y2 <- c(d$y[-1], NA) d$x2 <- c(d$x[-1], NA) d <- d[-findInterval(unique(d$id), d$id), ] # remove last row for each group plot(stackOne[, 3:2], pch=20) # clip to region above the threshold clip(min(stackOne$x), max(stackOne$x), threshold, max(stackOne$y)) segments(d$x, d$y, d$x2, d$y2, lwd=2) # clip to region below the threshold clip(min(stackOne$x), max(stackOne$x), min(stackOne$y), threshold) segments(d$x, d$y, d$x2, d$y2, lwd=2, col='red') points(stackOne[, 3:2], pch=20) # plot points again so they lie over lines 

base package, changing line colors

ggplot:

If you need or need to use ggplot , you can consider the following ...

One solution is to use geom_line(aes(group=id, color = y < 2.2)) , however this will assign colors based on the y-value of the point at the beginning of each segment. I believe that you want to change the color not only at the nodes, but everywhere where the line crosses your given threshold of 2.2. I'm not so familiar with ggplot, but one way to achieve this is to make a higher resolution version of the data by creating new points along the lines that connect your existing points, and then use the color = y < 2.2 argument to achieve the desired effect.

For instance:

 threshold <- 2.2 # set colour-transition threshold yres <- 0.01 # y-resolution (accuracy of colour change location) d <- stackOne # for code simplification # new cols for point coordinates of line end d$y2 <- c(d$y[-1], NA) d$x2 <- c(d$x[-1], NA) d <- d[-findInterval(unique(d$id), d$id), ] # remove last row for each group # new high-resolution y coordinates between each pair within each group y.new <- apply(d, 1, function(x) { seq(x['y'], x['y2'], yres*sign(x['y2'] - x['y'])) }) d$len <- sapply(y.new, length) # length of each series of points # new high-resolution x coordinates corresponding with new y-coords x.new <- apply(d, 1, function(x) { seq(x['x'], x['x2'], length.out=x['len']) }) id <- rep(seq_along(y.new), d$len) # new group id vector y.new <- unlist(y.new) x.new <- unlist(x.new) d.new <- data.frame(id=id, x=x.new, y=y.new) p <- ggplot(d.new, aes(x=x,y=y)) + geom_line(aes(group=d.new$id, color=d.new$y < threshold))+ geom_point(data=stackOne)+ scale_color_discrete(sprintf('Below %s', threshold)) p 

conditional line color - ggplot

There may be a way to do this through ggplot functions, but in the meantime I hope this helps. I could not figure out how to draw ggplotGrob in a cropped viewport (rather, it just scales the graph). If you want the color to be determined by some x-value threshold, this would obviously require some tweaking.

+9
source

Source: https://habr.com/ru/post/1399518/


All Articles