r - ggplot2 - create a shaded region between two geom_abline layers

前端 未结 1 845
余生分开走
余生分开走 2020-12-29 09:18

There are a few posts regarding the use of shaded areas in ggplot2, but I don\'t think any exactly answer my question. I have two slopes for lines across a number of conditi

相关标签:
1条回答
  • 2020-12-29 09:31

    Personally, I think that creating the data frames and using geom_ribbon is the elegant solution, but obviously opinions will differ on that score.

    But if you take full advantage of plyr and ggplot things can get pretty slick. Since your slopes and intercepts are all nicely stored in a dataframe anyway, we can use plyr and a custom function to do all the work:

    dat <- data.frame(cond1=c("a","a","b","b"),
              cond2=c("c","d","c","d"),
              x=c(1,5),
              y=c(1,5),
              sl=c(1,1.2,0.9,1.1),
              int=c(0,0.1,0.1,0),
              slopeU=c(1.1,1.3,1.2,1.2),
              slopeL=c(.9,1,0.7,1))
    
    genRibbon <- function(param,xrng){
        #xrng is a vector of min/max x vals in original data
        r <- abs(diff(xrng))
        #adj for plot region expansion
        x <- seq(xrng[1] - 0.05*r,xrng[2] + 0.05*r,length.out = 3)
        #create data frame
        res <- data.frame(cond1 = param$cond1,
                          cond2 = param$cond2,
                          x = x,
                          y = param$int + param$sl * x,
                          ymin = param$int + param$slopeL * x,
                          ymax = param$int + param$slopeU * x)
        #Toss the min/max x vals just to be safe; needed them 
        # only to get the corresponding y vals
        res$x[which.min(res$x)] <- -Inf
        res$x[which.max(res$x)] <- Inf
        #Return the correspondinng geom_ribbon
        geom_ribbon(data = res,aes(x = x,y=y, ymin = ymin,ymax = ymax,
                                   fill = cond1,colour = NULL),
                    alpha = 0.5)
    }
    
    ribs <- dlply(dat,.(cond1,cond2),genRibbon,xrng = c(1,5))
    

    The extra slick thing here is that I'm discarding the generated data frames completely and just returning a list of geom_ribbon objects. Then they can simply be added to our plot:

    p + ribs + 
        guides(fill = guide_legend(override.aes = list(alpha = 0.1)))
    

    I overrode the alpha aesthetic in the legend because the first time around you couldn't see the diagonal lines in the legend.

    enter image description here

    I'll warn you that the last line there that generates the plots also throws a lot of warnings about invalid factor levels, and I'm honestly not sure why. But the plot looks ok.

    0 讨论(0)
提交回复
热议问题