如何以特定值为条件获取geom_line的多种颜色

use*_*711 4 r ggplot2

我有以下数据框,我想绘制.我想知道是否有可能将连接我的结果变量(stackOne $ y)的部分线以不同颜色着色,具体取决于它是否小于某个值.例如,我希望部分线条在2.2以下变成红色.

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
Run Code Online (Sandbox Code Playgroud)

谢谢!

jba*_*ums 9

你在这里至少有几个选择.第一个是非常简单,一般(因为它不仅限于直线段)和精确,但使用基础plot而不是ggplot.第二种用途ggplot,但稍微复杂一点,颜色过渡不会100%精确(但足够接近,只要你指定一个合适的分辨率......继续阅读).

基础:

如果您愿意使用base绘图功能而不是ggplot,您可以将绘图区域剪切到阈值(2.2)以上,然后以您喜欢的颜色绘制线段,然后剪切到阈值以下的区域,并再次绘制为红色.虽然第一个剪辑是严格不必要的,但它可以防止过度绘制不同的颜色,这看起来有点哑.

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
Run Code Online (Sandbox Code Playgroud)

基础包,改变线条颜色

ggplot:

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

一种解决方案是使用geom_line(aes(group=id, color = y < 2.2)),但是这将基于每个段开始处的点的y值来分配颜色.我相信你不仅要在节点上进行颜色变换,而且要想在一条线超过你给定的2.2的阈值时进行颜色变化.我并不熟悉ggplot,但实现这一目标的一种方法是通过沿连接现有点的线创建新点来制作更高分辨率的数据版本,然后使用该color = y < 2.2参数来实现所需的效果.

例如:

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
Run Code Online (Sandbox Code Playgroud)

条件线颜色 -  ggplot

通过ggplot函数可能有一种方法可以做到这一点,但在此期间我希望这会有所帮助.我无法弄清楚如何画一个ggplotGrob剪辑viewport(而不是它似乎只是缩放图).如果你想让颜色以某个x值阈值为条件,那么显然需要进行一些调整.

  • 感谢您的解决方案,@jbaums!我冒昧地将其更新为 dplyr 以及 R 这些天可以做的较新的花哨的东西。任何有兴趣的人,你可以在这里查看代码:http://opiateforthemass.es/articles/dwd-daten/ (3认同)

teu*_*and 7

受到人们对一个较新但相关问题的回答的鼓励,我还将在这里分享一个更容易使用的问题近似值。

我们可以使用ggforce::geom_link2()插值线并after_stat()在插值后分配正确的颜色,而不是精确地插值正确的值。如果您想要更高的精度,可以增加n该函数的值。

library(ggplot2)
library(ggforce)
#> Warning: package 'ggforce' was built under R version 4.0.3

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_link2(
    aes(group = id,
        colour = after_stat(y < 2.2))
  ) +
  scale_colour_manual(
    values = c("black", "red")
  )
Run Code Online (Sandbox Code Playgroud)

reprex 包(v1.0.0)创建于 2021-03-26