问题描述
我要绘制以下数据框。我想知道是否可以将连接我的结果变量(stackOne $ y)的线的部分上不同的颜色,具体取决于它是否小于某个值。例如,我希望低于2.2的行的部分为红色。
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.
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))
ggplot(stackOne, aes(x = x, y = y)) +
geom_point() +
geom_line(aes(group = id))
谢谢!
推荐答案
您在这里至少有两个选择。第一个非常简单,通用(因为它不仅限于直线段)而且很精确,但是使用基本 plot
而不是 ggplot
。第二个使用 ggplot
,但是稍微复杂一点,并且颜色过渡不会精确到100%(但是足够接近,只要您指定合适的分辨率即可...阅读
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
如果您愿意使用 base
绘图函数而不是 ggplot
,您可以将绘图区域裁剪到阈值(2.2)以上,然后绘制线段以您喜欢的颜色显示,然后裁剪到阈值以下的区域,然后再次以红色绘制。虽然绝对没有必要使用第一个剪辑,但是它可以防止过度绘制不同的颜色,这些颜色看起来可能有些过时。
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:
如果您希望或需要使用 ggplot
,可以考虑以下...
If you want or need to use ggplot
, you can consider the following...
一种解决方案是使用 geom_line(aes(group = id,color = y< 2.2))
,但是这将根据每个线段开始处的点的y值分配颜色。我相信您不仅希望在节点处而且要在一条线超过给定的阈值2.2的地方进行颜色更改。我对ggplot并不是很熟悉,但是一种实现方法是通过沿连接现有点的直线创建新点来制作更高分辨率的数据,然后使用颜色= y< 2.2
参数以达到理想的效果。
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.
例如:
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
也许可以通过ggplot函数来完成此操作,但与此同时,我希望这会有所帮助。我不知道如何将 ggplotGrob
绘制到裁剪后的视口
中(相反,它似乎只是在缩放比例) )。如果您希望颜色以某个x值阈值为条件,则显然需要进行一些调整。
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颜色不同的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!