如何根据特定值获取geom_line的多种颜色 [英] How to obtain multiple colours for geom_line conditional on a specific value

查看:1079
本文介绍了如何根据特定值获取geom_line的多种颜色的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有我想要绘制的以下数据框。我想知道是否可以使用不同的颜色对连接我的结果变量(stackOne $ y)的部分线进行着色,具体取决于它是否小于某个值。例如,我希望部分线下降到2.2以下的颜色是红色。

  id< -rep(c( 1,2,3),每个= 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

谢谢!

解决方案

这里至少有几个选项。第一种是非常简单的,一般的(因为它不限于直线段)和精确的,但是使用base plot 而不是 ggplot code>。第二个使用 ggplot ,但稍微复杂一些,并且颜色转换不会100%精确(但是只要您指定了适当的分辨率就足够了......阅读)
$ b

base:



如果您愿意使用 base 绘图函数而不是 ggplot ,您可以将绘图区域限制在阈值(2.2)以上,然后绘制细分以您喜欢的颜色显示,然后剪切到阈值以下的区域,再以红色绘图。虽然第一个剪辑是完全不必要的,但它可以防止重叠绘制不同的颜色,这看起来有点不合适。

 阈值< -  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))
#创建第二个df来存放分段数据
d < - stackOne
d $ y2< - (d $ y [-1],NA)
d $ x2 <-c(d $ x [-1],NA)
d <-d [-findInterval(unique(d $ id),d $ id),]#删除每个组的最后一行

plot(stackOne [,3:2],pch = 20)
# b $ b clip(min(stackOne $ x),max(stackOne $ x),threshold,max(stackOne $ y))
segments(d $ x,d $ y,d $ x2,d $ y2,
#剪辑到阈值以下的区域
剪辑(min(stackOne $ x),max(stackOne $ x),min(stackOne $ y),阈值)
segments( d $ x,d $ y,d $ x2,d $ y2,lwd = 2,col ='red')
points(stackOne [,3:2],pch = 20)#plot points points,躺在行



ggplot



如果您想要或需要使用 ggplot ,你可以考虑以下内容......



一个解决方案是使用 geom_line(aes(group = id,color = y< 2.2)),但是这会根据每个片段开头的点的y值来分配颜色。我相信你希望颜色不仅在节点上发生变化,而且在任何一条线越过给定的阈值2.2时。我并不是那么熟悉ggplot,但实现这一目标的一种方法是通过沿连接现有点的线创建新点来创建更高分辨率的数据,然后使用 color = y< 2.2 参数可以达到预期的效果。



例如:

 阈值< -  2.2#设置颜色转换阈值
yres < - 0.01#y分辨率(颜色改变位置的准确性)

d < - stackOne #代码简化
#行结束点坐标的新cols
d $ y2 < - c(d $ y [-1],NA)
d $ x2 < - c(d $ x [-1],NA)
d <-d [-findInterval(unique(d $ id),d $ id),]#删除每个组的最后一行
#新的高分辨率(x,y',x'',y''),yres(x,y',y')的每个对之间的y坐标。 * sign(x ['y2'] - x ['y']))
})
d $ len< - sapply(y.new,length)#每个系列点的长度
#与新y坐标对应的新的高分辨率x坐标
x.new应用(d,1,function(x){
seq(x ['x'],x ['x2'],length.out = x ['len'])
})
id < - rep(seq_along(y.new),d $ len)#new grou p id向量
y.new< - unlist(y.new)
x.new< - unlist(x.new)
d.new< - data.frame(id = x,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<阈值))+
geom_point(data = stackOne)+
scale_color_discrete(sprintf('Below%s',threshold))
p



可能有办法通过ggplot函数来做到这一点,但同时我希望这有助于。我无法弄清楚如何绘制一个 ggplotGrob 到一个修剪的 viewport 中(它似乎只是缩放绘图)。如果你想让颜色取决于某个x值阈值,这显然需要一些调整。


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

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!

解决方案

You have at least a couple of options here. The first is quite simple, general (in that it's not limited to straight-line segments) and precise, but uses base plot rather than ggplot. The second uses ggplot, but is slightly more complicated, and colour transition will not be 100% precise (but near enough, as long as you specify an appropriate resolution... read on).

base:

If you're willing to use base plotting functions rather than ggplot, you could clip the plotting region to above the threshold (2.2), then plot the segments in your preferred colour, and subsequently clip to the region below the threshold, and plot again in red. While the first clip is strictly unnecessary, it prevents overplotting different colours, which can look a bit dud.

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

ggplot:

If you want 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 colours based on the y-value of the point at the beginning of each segment. I believe you want to have the colour change not just at the nodes, but wherever a line crosses your given threshold of 2.2. I'm not all that familiar with ggplot, but one way to achieve this is to make a higher-resolution version of your 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 example:

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

There may well be a way to do this through ggplot functions, but in the meantime I hope this helps. I couldn't work out how to draw a ggplotGrob into a clipped viewport (rather it seems to just scale the plot). If you want colour to be conditional on some x-value threshold instead, this would obviously need some tweaking.

这篇关于如何根据特定值获取geom_line的多种颜色的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆