2012-03-12 420 views
13

关于ggplot2中阴影区域的使用有一个fewposts,但我不认为任何回答我的问题。我有两条斜线用于满足多种条件的线条,我想遮蔽它们之间的区域。下面是示例性数据:r - ggplot2 - 在两个geom_abline图层之间创建一个阴影区域

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)) 

这里,sl是从单独的拟合过程的平均斜率参数,和slopeUslopeL表示在每个条件下的斜率估计上下置信区域。拦截限制为相同。下面的代码绘制每个条件使用一些刻面的最佳拟合线:

p <- ggplot(dat,aes(x=x,y=y,colour=cond1)) 
p <- p + facet_grid(. ~ cond2) 
p <- p + geom_blank() 
p <- p + geom_abline(aes(intercept=int,slope=sl,colour=cond1),data=dat) 
p 

我想在alpha=.5在对应于添加由intercept=int, slope=slopeUintercept=int, slope=slopeL的情节和阴影它们(例如之间的区域定义的行内cond1颜色)。

我意识到,通过一点操作,我可以创建一个数据框,为至少两个x值指定这些行的值,然后绘制相应的geom_ribbon或geom_polygon以创建阴影区域,但是我想查找更多优雅的方案。或者是从斜坡上手动指定一些坐标并拦截唯一的方法?我将如何最好地创建所需的数据框(这将需要有比原始框架更多的行来说明条件和x,y对的所有组合)。

回答

10

我个人认为创建数据帧和使用geom_ribbon优雅的解决方案,但显然意见会在该分数上有所不同。

但如果你plyrggplot充分利用事情会变得非常光滑。由于您的斜率和截距都很好地保存在数据帧,无论如何,我们可以使用plyr和自定义函数来完成所有的工作:

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)) 

这里额外的圆滑的事情是,我丢弃产生数据框完全返回一个geom_ribbon对象列表。然后,他们可以简单地添加到我们的剧情:

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

我在传奇推翻了alpha审美,因为你周围的第一次看不到传说中的对角线。

enter image description here

我会提醒你,最后一行有生成的地块也引发了很多关于无效因子水平的警告,我真的不知道为什么。但情节看起来不错。

+0

太棒了;谢谢乔兰。 – tsawallis 2012-03-13 15:34:14

+0

所以,基本上与我应用的问题一起工作,但我无法将阴影区域的颜色设置为cond1,即使通过精确运行您的解决方案。填充的色带区域为灰色(alpha = .5),但也有细实线边框。我哪里错了?这可能是一个ggplot2版本的差异?我在0.9.0上。我使用的ggplot命令与原始文章中的一样,在下面粘贴了'p + rib + guides(fill = guide_legend(override.aes = list(alpha = 0.1)))'。 – tsawallis 2012-03-13 16:11:28

+0

@waldog对不起,只是错过了一些复制粘贴我的代码。您只需在顶层'ggplot()'调用或函数内的'geom_ribbon'调用中在'aes()'中添加'fill = cond1'。我会立即编辑... – joran 2012-03-13 16:15:58