【问题标题】:Different colours of geom_line above and below a specific value特定值上下不同颜色的geom_line
【发布时间】:2012-03-03 04:17:01
【问题描述】:

我有以下要绘制的数据框。我想知道是否可以将连接我的结果变量(stackOne$y)的部分线用不同的颜色着色,具体取决于它是否小于某个值。例如,我希望低于 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))

ggplot(stackOne, aes(x = x, y = y)) +
    geom_point() +
    geom_line(aes(group = id))

谢谢!

【问题讨论】:

    标签: r ggplot2 colors


    【解决方案1】:

    您在这里至少有几个选择。第一个非常简单、通用(因为它不限于直线段)和精确,但使用基础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
    

    ggplot:

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

    一种解决方案是使用geom_line(aes(group=id, color = y &lt; 2.2)),但是这将根据每个段开始处的点的 y 值分配颜色。我相信您不仅希望在节点处进行颜色更改,还希望在一条线越过您给定的 2.2 阈值的任何地方进行颜色更改。我对 ggplot 不是很熟悉,但实现这一点的一种方法是通过沿着连接现有点的线创建新点来制作数据的更高分辨率版本,然后使用 color = y &lt; 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
    

    很可能有一种方法可以通过 ggplot 函数来做到这一点,但同时我希望这会有所帮助。我不知道如何将ggplotGrob 绘制成剪裁的viewport(它似乎只是缩放情节)。如果您希望颜色以某个 x 值阈值为条件,这显然需要一些调整。

    【讨论】:

    • 谢谢。我听说 melt 功能也可以解决此类问题,但这听起来是一个很好的解决方案。
    • 我已经编辑了解决方案以包含一个使用基图和clip 的方法。
    • ggplotGrob 使用内部视口本身,这就是剪辑不起作用的原因。
    • @baptiste:谢谢你。我在 Hadley 那里找到了your discussion,但不确定你是否找到了解决方案(我假设你没有找到)。为清除它而欢呼。
    • 感谢您的解决方案,@jbaums!我冒昧地将它更新为 dplyr 和 R 可以做的新奇的东西。有兴趣的朋友可以在这里查看代码:opiateforthemass.es/articles/dwd-daten
    【解决方案2】:

    受到answer 中的人们的鼓励,提出了一个更新但相关的问题,我还将在这里分享一个更易于使用的问题近似值。

    可以使用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")
      )
    

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多