Подтвердить что ты не робот

R - ggplot2 - создать заштрихованную область между двумя слоями geom_abline

Есть несколько сообщений об использовании затененных областей в ggplot2, но я не подумайте, что точно ответьте на мой вопрос. У меня есть два наклона для линий в нескольких условиях, и я хотел бы затенять область между ними. Вот пример данных:

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 - средний параметр наклона от отдельной процедуры подгонки, а slopeU и slopeL представляют верхнюю и нижнюю доверительные области в оценке наклона в каждом условии. Перехваты ограничиваются одинаковыми. Следующий код отображает наилучшие фитинги для каждого условия, используя некоторую огранку:

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

Я хотел бы добавить строки, определенные intercept=int, slope=slopeU и intercept=int, slope=slopeL, в график и затенять область между ними (например, в alpha=.5 в соответствующем цвете cond1).

Я понимаю, что с небольшой манипуляцией я мог бы создать кадр данных, определяющий значения этих строк, по крайней мере для двух значений x, а затем построить соответствующий geom_ribbon или geom_polygon для создания заштрихованной области, однако я бы хотел найти более элегантный решение. Или вручную указывать некоторые координаты со склонов и перехватывает единственный способ? Как бы я лучше всего создал требуемый фрейм данных (для которого нужно будет иметь больше строк, чем исходный кадр, для учета всех комбинаций условий и x, y пар).

4b9b3361

Ответ 1

Лично я считаю, что создание фреймов данных и использование geom_ribbon - элегантное решение, но, судя по всему, мнения будут отличаться от этого.

Но если вы в полной мере воспользуетесь plyr и ggplot, все может стать довольно гладким. Так как ваши склоны и перехваты все хорошо хранятся в фреймворке данных, мы можем использовать 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

Я предупреждаю вас, что последняя строка, которая генерирует графики, также содержит множество предупреждений о недопустимых уровнях факторов, и я честно не знаю, почему. Но сюжет выглядит нормально.