geom_ribbon() with varying fill

2,367 views
Skip to first unread message

Jakub Szewczyk

unread,
Mar 12, 2011, 5:11:32 AM3/12/11
to ggplot2
Hi,

I'm trying to plot a ribbon that has its fill varying. So far I was
able to simulate it with geom_linerange:

geom_linerange(aes(x=ms,ymin=HC, ymax=LC, color=corelation), size=2)

so that adjacent lines stick and fill all the space. But this is not
perfect solution, because sometimes they slightly overlap, and lead to
'rough' edges.

I also thought about subdividing the x-axis domain into a few parts,
and plotting separate ribbons for them, using different colors
(basing on 'corelation' value). But this would be a dirty solution - I
would have to define new columns for each of the subdomains
(containins separate specifications for x, ymin and ymax for each of
the subdomains), and there would be still gaps in between adjacent
ribbons.

I understand the problem with geom_ribbon() not accepting varying fill
has something to do with the fact that fill is defined for discrete
points, while ribbon is continuous. But is there any other solution
around this?

Best,
Jakub


Hadley Wickham

unread,
Mar 13, 2011, 1:12:13 PM3/13/11
to Jakub Szewczyk, ggplot2
Hi Jakub,

If you could provide a small reproducible example
(https://github.com/hadley/devtools/wiki/Reproducibility) it might
make easier to others suggest possible approaches.

Hadley

> --
> You received this message because you are subscribed to the ggplot2 mailing list.
> Please provide a reproducible example: http://gist.github.com/270442
>
> To post: email ggp...@googlegroups.com
> To unsubscribe: email ggplot2+u...@googlegroups.com
> More options: http://groups.google.com/group/ggplot2
>

--
Assistant Professor / Dobelman Family Junior Chair
Department of Statistics / Rice University
http://had.co.nz/

Jakub Szewczyk

unread,
Mar 13, 2011, 1:54:31 PM3/13/11
to ggplot2

Hi Hadley,

I am sorry, I thought this is a well-known feature/bug of ggplot2 I
was showing, this is why I provided no real example. Here it goes:

N <- 100
df <- data.frame(time=1:N, LC=rnorm(N, 70, 20), HC=rnorm(N, 20, 20),
corr=seq(-1, 0.98, 0.02))
ggplot(df, aes(x=time)) + geom_ribbon(aes(ymin=HC, ymax=LC,
fill=corr))


The above doesn't work ("Aesthetics can not vary with a ribbon")
This simulates it but is not ideal:

ggplot(df, aes(x=time)) + geom_linerange(aes(x=time, ymin=HC, ymax=LC,
color=corr), size=2)


Finally, I found a solution how to do it (thanks to James McCreight
for turning my attention to geom_polygon()!), but it needs some more
playing around:

mdf <- melt (df, id.vars=c("time", "corr"))
mdf <- mdf[order (mdf$time, mdf$variable),]
mdf <- rbind (mdf[1:(nrow (mdf) - 2),], mdf[3:nrow (mdf),])
mdf$grouping <- rep (rep (1:(N-1), each=2), 2)
mdf <- mdf[order (mdf$grouping, mdf$time),]
mdf$reorder <- rep (c (1, 2, 4, 3), (N-1))
mdf <- mdf[order (mdf$grouping, mdf$reorder),]
ggplot (mdf, aes (x = time, y=value)) + geom_polygon (aes (fill=corr,
group=grouping))


I'm new to R, so tt could be probably written a little better. Anyway,
the final effect is exactly what I wanted to get. But of course it
would be much more natural to do it with geom_ribbon().

BTW - thanks for a great library - it really rocks!

Jakub
Reply all
Reply to author
Forward
0 new messages