2012-03-12 11 views
13

Hay un fewposts con respecto al uso de áreas sombreadas en ggplot2, pero no creo que ninguna responda exactamente mi pregunta. Tengo dos pendientes para líneas a través de una serie de condiciones, y me gustaría sombrear la región entre ellos. Aquí es ejemplo de datos:r - ggplot2 - crea una región sombreada entre dos capas 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)) 

Aquí, sl es el parámetro de pendiente media de un procedimiento de ajuste separada, y slopeU y slopeL representan regiones superior e inferior de confianza en la estimación de la pendiente en cada condición. Las intersecciones están obligadas a ser lo mismo. El código siguiente representa los mejores líneas de ajuste para cada condición utilizando algunos de facetado:

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 

me gustaría añadir las líneas definidas por intercept=int, slope=slopeU y intercept=int, slope=slopeL a la trama y la sombra de la región entre ellos (por ejemplo, en alpha=.5 en el correspondiente cond1 color).

Reconozco que con un poco de manipulación podría crear un marco de datos que especifique los valores de estas líneas para al menos dos valores x, luego graficar el geom_ribbon o geom_polygon correspondiente para crear la región sombreada, pero me gustaría encontrar un solución elegante. ¿O está especificando manualmente algunas coordenadas de las pendientes e intercepta de la única manera? ¿Cómo puedo crear mejor el marco de datos requerido (que necesitará tener más filas que el marco original para tener en cuenta todas las combinaciones de condiciones y los pares x, y)?

Respuesta

10

Personalmente, creo que la creación de los marcos de datos y el uso de geom_ribbones la solución elegante, pero obviamente las opiniones diferirán en ese punto.

Pero si se toma el máximo provecho de plyr y ggplot las cosas pueden ser bastante resbaladiza. Desde sus pendientes e intersecciones están muy bien almacenados en una trama de datos de todos modos, podemos utilizar plyr y una función personalizada para hacer todo el trabajo:

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

La cosa extra mancha de aquí es que estoy descartando el generé marcos de datos completamente y simplemente devolviendo una lista de objetos geom_ribbon. Entonces simplemente se puede añadir a nuestra parcela:

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

me hicieron caso omiso de la estética alpha en la leyenda, porque la primera vez que no podía ver las líneas diagonales en la leyenda.

enter image description here

Yo te advertiremos que la última línea hay que genera las parcelas también lanza una gran cantidad de advertencias acerca de los niveles de factor no válidos, y, sinceramente, no estoy seguro de por qué. Pero la trama se ve bien.

+0

Eso es increíble; gracias Joran. – tsawallis

+0

Así que básicamente funciona con mi problema aplicado, pero no puedo obtener los colores en las regiones sombreadas para cond1, incluso ejecutando exactamente su solución. Las regiones de la cinta llena son grises (en alfa = .5) pero también tienen bordes finos de línea sólida. ¿Dónde estoy equivocado? ¿Podría ser esta una diferencia de versión ggplot2? Estoy en 0.9.0. El comando ggplot que estoy usando es como en la publicación original, con 'p + ribs + guides (fill = guide_legend (override.aes ​​= list (alpha = 0.1)))' pegado debajo. – tsawallis

+0

@waldog Lo siento, me perdí un poco cuando copié y pegué mi código.Solo tiene que agregar 'fill = cond1' en' aes() 'en la llamada' ggplot() 'de nivel superior o en la llamada' geom_ribbon' dentro de la función. Voy a editar momentáneamente ... – joran

Cuestiones relacionadas