Clip data to zoom color scales (suggestion with workaround)

22 views
Skip to first unread message

Jon Olav Vik

unread,
Aug 22, 2009, 8:35:09 AM8/22/09
to ggplot2
I would like to set manual limits on the colour scale when using
geom_tile, so that outliers will not compress the color scale for the
remaining values. Although I can specify a limits= argument to
scale_fill_continuous and friends, values outside the limits leave
gaps in the plot.

What I'm after is similar functionality for the color axis as for x
and y axes, which have separate limits on scales and coordinate
systems (cf. chapter 7.3.3 of the ggplot2 book). Scale limits subset
the data, whereas coordinate limits just perform a visual zoom.

I'm working around this problem as shown below, using a stat to clip
values to specified limits. Here's a shortened version of the example,
assuming stat_clip is defined as below.

library(reshape)
x <- melt(matrix(c(-10,1:10,20),3,4)) # sample data with outliers
clim <- c(3,8) # color axis limits
p <- qplot(X1, X2, data=x, geom="tile", fill=value) +
scale_fill_continuous(limits=clim)
p + geom_text(aes(label=value)) # plot with gaps
p + stat_clip(limits=clim) + geom_text(aes(label=value)) # plot
without gaps

I'm posting it here in case it might be useful to others; if there are
neater ways to do this (e.g. getting the limits from the argument
passed to the colour scale), I'd be happy to learn.

Best regards,
Jon Olav

== stat_clip.R ==
# stat_clip to zoom color scales without hiding data that fall outside
limits
library(ggplot2)

clip <- function(x, limits=c(-Inf, Inf))
pmin(pmax(limits[1], x), limits[2])

StatClip <- proto(Stat, {
objname <- "clip"
desc <- "Replace extreme data by lower and upper limits"

# # Unfortunately, setting default_geom here will override the
geom_text()
# # used in the example below.
default_geom <- function(.) GeomTile
calculate_groups <- function(., data, limits=c(-Inf, Inf), ...) {
# print(data) # useful to see what's available for the
function
data$fill <- clip(data$fill, limits)
return(data)
}
icon <- function(.) textGrob("f(x) = clip(x,xmin,xmax)", gp=gpar
(cex=1.2))

desc_outputs <- list()

examples <- function(.) {
# Zoom color scale without omitting values outside limits
library(reshape)
x <- melt(matrix(c(-10,1:10,20),3,4)) # sample data with
outliers
clim <- c(3,8) # color axis limits
p <- qplot(X1, X2, data=x, geom="tile", fill=value) +
geom_text(aes(label=value)) + theme_bw()
plots <- list(p, p + scale_fill_continuous(limits=clim),
p + scale_fill_continuous(limits=clim) +
stat_clip(limits=clim) + geom_text(aes(label=value))
)
# adapted from ggplot book chapter 8.4.2, "rectangular grids"
vp <- function(i) viewport(layout.pos.row=1, layout.pos.col=i)
grid.newpage()
pushViewport(viewport(layout=grid.layout(1,3)))
invisible(mapply(print, plots, vp=lapply(1:3,vp)))
}
})

stat_clip <- StatClip$build_accessor()

StatClip$examples()

hadley wickham

unread,
Aug 23, 2009, 9:11:18 AM8/23/09
to Jon Olav Vik, ggplot2
On Sat, Aug 22, 2009 at 7:35 AM, Jon Olav Vik<jon...@gmail.com> wrote:
>
> I would like to set manual limits on the colour scale when using
> geom_tile, so that outliers will not compress the color scale for the
> remaining values. Although I can specify a limits= argument to
> scale_fill_continuous and friends, values outside the limits leave
> gaps in the plot.
>
> What I'm after is similar functionality for the color axis as for x
> and y axes, which have separate limits on scales and coordinate
> systems (cf. chapter 7.3.3 of the ggplot2 book). Scale limits subset
> the data, whereas coordinate limits just perform a visual zoom.

Hmmm, I disagree that this is equivalent to coordinate zooming, but I
can see how it would be useful. I'd suggest making it slightly more
general by using the following (untested) calculate_groups function:

calculate_groups <- function(., data, limits = list(), ...) {
for(aes in names(limits)) {
data[[aes]] <- clip(data[[aes]], limits[[aes]])
}
data
}

Then you could say stat_clip(limits = list(fill = c(1, 5), x = c(1, 5)) etc.

Hadley


--
http://had.co.nz/

Reply all
Reply to author
Forward
0 new messages