2012-03-12 5 views
13

Есть fewposts относительно использования затененных областей в ggplot2, но я не думаю, что точно ответит на мой вопрос. У меня есть два наклона для линий в нескольких условиях, и я хотел бы затенять область между ними. Вот пример данные: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 является средним параметра наклона от отдельной процедуры подгонки и 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 color).

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

ответ

10

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

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

+0

Так что в основном я работаю с моей прикладной проблемой, но я не могу получить цвета в затененных областях до cond1, даже с помощью вашего решения точно. Заполненные области ленты серы (при альфа = .5), но также имеют тонкие сплошные границы линий. Где я иду не так? Может ли это быть разницей версии ggplot2? Я на 0.9.0. Команда ggplot, которую я использую, такая же, как в исходном сообщении, с 'p + ribs + guide (fill = guide_legend (override.aes ​​= list (alpha = 0.1))), вставленный ниже. – tsawallis

+0

@waldog Простите, просто пропустил немного, когда копировал + вставлял мой код.Вам просто нужно добавить 'fill = cond1' в' aes() 'либо в вызове ggplot() верхнего уровня, либо в вызове' geom_ribbon' внутри функции. Я отредактирую мгновенно ... – joran

Смежные вопросы