How to clip, rather than remove, out-of-limit bars?

2,556 views
Skip to first unread message

Stuart Luppescu

unread,
Jul 15, 2013, 1:39:31 PM7/15/13
to ggplot2
Hello ggplotters, I'm able to produce the graph I need fine but when I
limit the range of the y-axis, the whole look of the graph changes. This
is fine:

cut.offs <- c(209, 284, 339, 400)

x <- seq(1, 4, by = .05) * 75
y_un <- (cut.offs[1] - x) / .9
Unsatisfactory <- ifelse(y_un < 0, 0, y_un)

y_ni <- (cut.offs[2] - x) / .9
Developing <- ifelse(y_ni < 0, 0, y_ni)

y_pr <- (cut.offs[3] - x) / .9
Proficient <- ifelse(y_pr < 0, 0, y_pr)

y_ex <- (cut.offs[4] - x) / .9
Excellent <- ifelse(y_ex < 0, 0, y_ex)

plot.df <- data.frame(Obs.score=x, Unsatisfactory, Developing, Proficient, Excellent)

plot.long.df <- melt(plot.df, id.vars="Obs.score")

names(plot.long.df)[2] <- "Summative Category"

ggplot(plot.long.df, aes(x=Obs.score, y=value, fill=`Summative Category`)) +
geom_area() +
scale_y_continuous(name="Needed Student Growth Score") +
labs(x="Observation Score", title="Required Student Growth Score for Summative Category\nGiven Observation Score")

Actually, it's impossible to get a Student Growth Score of more than
100. But when I include limits=c(0, 100) in the scale specification, the
whole shape of the graph changes (it looks like saw teeth). It's like
the parts of the area where the y-value is more than 100 are removed
rather than just clipping the height of the area to 100. Is there a way
around this?

Thanks in advance.

--
Stuart Luppescu <s...@ccsr.uchicago.edu>
University of Chicago

Brandon Hurr

unread,
Jul 15, 2013, 1:43:55 PM7/15/13
to Stuart Luppescu, ggplot2
I think you need to use coord_cartesian() to set your limits. 

Stuart Luppescu

unread,
Jul 15, 2013, 1:57:33 PM7/15/13
to Brandon Hurr, ggplot2
On Mon, 2013-07-15 at 18:43 +0100, Brandon Hurr wrote:
> I think you need to use coord_cartesian() to set your limits.

Thanks, Brandon. That did the trick.

Ben Bolker

unread,
Jul 15, 2013, 2:14:17 PM7/15/13
to ggp...@googlegroups.com
On 13-07-15 01:57 PM, Stuart Luppescu wrote:
> On Mon, 2013-07-15 at 18:43 +0100, Brandon Hurr wrote:
>> I think you need to use coord_cartesian() to set your limits.
>
> Thanks, Brandon. That did the trick.
>

As of more recent versions of ggplot
there's another, slightly more elegant way to do this, which isn't
terribly well documented/well-known, which is to load the scales
library and use oob=squish (can anyone point to a canonical reference
for this? I always just google "oob squish". Maybe someone should
ask & answer this on Stack Overflow ...)

e.g. see https://github.com/hadley/ggplot2/issues/383
(reporting a bug which has since been fixed, I think)

cut.offs <- c(209, 284, 339, 400)
x <- seq(1, 4, by = .05) * 75
y_un <- (cut.offs[1] - x) / .9
Unsatisfactory <- ifelse(y_un < 0, 0, y_un)
y_ni <- (cut.offs[2] - x) / .9
Developing <- ifelse(y_ni < 0, 0, y_ni)
y_pr <- (cut.offs[3] - x) / .9
Proficient <- ifelse(y_pr < 0, 0, y_pr)
y_ex <- (cut.offs[4] - x) / .9
Excellent <- ifelse(y_ex < 0, 0, y_ex)
plot.df <- data.frame(Obs.score=x,
Unsatisfactory, Developing, Proficient, Excellent)

## there's probably a cleverer way to do this
## data manipulation with cut() ...

library(reshape2)
plot.long.df <- melt(plot.df, id.vars="Obs.score")
names(plot.long.df)[2] <- "Summative Category"

library(ggplot2)
g0 <- ggplot(plot.long.df,
aes(x=Obs.score, y=value, fill=`Summative Category`)) +
geom_area() +
labs(x="Observation Score", title="Required Student Growth Score for
Summative Category\nGiven Observation Score",y="Needed Student Growth
Score")

## these are identical ...
g0 + ylim(0,100)
library(scales)
g0 + scale_y_continuous(limits=c(0,100),oob=censor)


g0 + coord_cartesian(ylim=c(0,100))
g0 + scale_y_continuous(limits=c(0,100),oob=squish)
## really wacky, but perhaps useful sometimes
g0 + scale_y_continuous(limits=c(0,100),oob=discard)

Reply all
Reply to author
Forward
0 new messages