Trouble Using geom_rect to Underlay Portion of Plot

1,025 views
Skip to first unread message

Scott N

unread,
Jun 13, 2011, 4:25:02 PM6/13/11
to ggplot2
I'm trying to add a rectangle behind a portion of my plot, but seem
unable to do so.

This works:

# Example data
FactorA=c("Home","Away","Home","Neutral","Home","Home","Away","Neutral","Home","Neutral")
FactorB=c("Group1","Group2","Group2","Group2","Group2","Group2","Group2","Group1","Group2","Group1")
YearQtr=c("2011.25","2011","2010.75","2010.5","2010.25","2010","2009.75","2009.5","2009.25","2009")
mydata<- data.frame(cbind(FactorA,FactorB,YearQtr))
# Create the plot with ggplot2
my.gg <- ggplot(mydata) +
geom_point(aes(FactorA,YearQtr,colour=factor(FactorB)),size=4) +
scale_y_discrete(breaks=c(2008,2009,2010,2011)) +

scale_color_manual(name="Group",values=c("darkolivegreen4","darkorange"))
+
theme_bw(11) +
opts(title = "View of Something Over Time") +
opts(axis.text.x=theme_text(angle=90, hjust=1))
my.gg

However, this doesn't do what I would expect. I get a "Error: Non-
continuous variable supplied to scale_x_continuous." error.

# Add a rectangle to the plot behind part of the area.
also.my.gg <- ggplot(mydata) +
geom_rect(aes(xmin=1,xmax=2,ymin=2009.5,ymax=2010.25,fill="gray")) +
geom_point(aes(FactorA,YearQtr,colour=factor(FactorB)),size=4) +
scale_y_discrete(breaks=c(2008,2009,2010,2011)) +

scale_color_manual(name="Group",values=c("darkolivegreen4","darkorange"))
+
theme_bw(11) +
opts(title = "View of Something Over Time") +
opts(axis.text.x=theme_text(angle=90, hjust=1))
also.my.gg

So, I add a scale_x_discrete the the code.

# Add a rectangle to the plot behind part of the area.
another.my.gg <- ggplot(mydata) +
geom_rect(aes(xmin=1,xmax=2,ymin=2009.5,ymax=2010.25,fill="gray")) +
geom_point(aes(FactorA,YearQtr,colour=factor(FactorB)),size=4) +
scale_y_discrete(breaks=c(2008,2009,2010,2011)) +

scale_color_manual(name="Group",values=c("darkolivegreen4","darkorange"))
+
theme_bw(11) +
opts(title = "View of Something Over Time") +
opts(axis.text.x=theme_text(angle=90, hjust=1))
another.my.gg

Now I don't get an error, but it doesn't look right. All of the data
is down at the bottom.

Any ideas??? Thanks.

Dennis Murphy

unread,
Jun 13, 2011, 9:29:36 PM6/13/11
to Scott N, ggplot2
Hi:

There are at least two things wrong here, only one of which has to do
with ggplot2.

# (1):
mydata<- data.frame(cbind(FactorA,FactorB,YearQtr))

You want YearQtr to be continuous (i.e., numeric), but you input it as
a character string. cbind() in this case will create a matrix of
character strings, since in a matrix, all elements must be of the same
mode. Wrapping data.frame around this converts it to a data frame, but
since you didn't use the option stringsAsFactors = FALSE, everything
gets read in as a factor. Observe:

> mydat<- data.frame(cbind(FactorA,FactorB,YearQtr))
> str(mydat)
'data.frame': 10 obs. of 3 variables:
$ FactorA: Factor w/ 3 levels "Away","Home",..: 2 1 2 3 2 2 1 3 2 3
$ FactorB: Factor w/ 2 levels "Group1","Group2": 1 2 2 2 2 2 2 1 2 1
$ YearQtr: Factor w/ 10 levels "2009","2009.25",..: 10 9 8 7 6 5 4 3 2 1

This is why you got the error message when you tried to use
scale_y_continuous(); as you have it, YearQtr is a factor, not a
numeric variable.

This is better for the purposes you intend:

mydata<- data.frame(FactorA, FactorB, YearQtr = as.numeric(YearQtr))
> str(mydata)
'data.frame': 10 obs. of 3 variables:
$ FactorA: Factor w/ 3 levels "Away","Home",..: 2 1 2 3 2 2 1 3 2 3
$ FactorB: Factor w/ 2 levels "Group1","Group2": 1 2 2 2 2 2 2 1 2 1
$ YearQtr: num 2011 2011 2011 2010 2010 ...

# (2)

In the call to generate the rectangle, you need to distinguish between
aesthetics that are mapped (variables) and those that are set to
single values (parameters/constants). In particular, you needed

geom_rect(aes(xmin=1, xmax=2, ymin=2009.5, ymax=2010.25), fill="gray")

Putting this all together, the following may be what you're after:

mydata<- data.frame(FactorA, FactorB, YearQtr = as.numeric(YearQtr))


# Create the plot with ggplot2

my.gg <- ggplot(mydata) + theme_bw(11) +
geom_point(aes(FactorA,YearQtr,colour=factor(FactorB)),size=4) +
scale_y_continuous(breaks=c(2008,2009,2010,2011)) +


scale_color_manual(name="Group",values=c("darkolivegreen4","darkorange")) +

geom_rect(aes(xmin=1, xmax=2, ymin=2009.5, ymax=2010.25),
fill="gray", alpha = 0.5) +


opts(title = "View of Something Over Time") +
opts(axis.text.x=theme_text(angle=90, hjust=1))
my.gg

It's not necessary to rotate the x-labels in this example - you don't
want your audience to strain to read the labels without need. Perhaps
your real example has many more levels and the rotation avoids
overplotting. I also inserted alpha transparency into the rectangle so
that the points are at least partially visible within it.

HTH,
Dennis

> --
> 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
>

Scott N

unread,
Jun 13, 2011, 10:42:59 PM6/13/11
to ggplot2
Dennis,

Thanks for the help. I had (in another version) used as.numeric, but
neglected to include it in my example. Even when I did that,
something wasn't right. I think it has to do with the other point you
are making-- the difference between aesthetics that are mapped vs. set
to a single value. I'm starting to see it, but am going to have to
experiment some more to make sure that I actually get it.

Regarding the rotation of the titles on the x axis, you are correct...
my real data has many more categories; I just produced a simplified
version of it for purposes of my question (and since I can't share the
actual data).

Thanks again,
Scott

Scott N

unread,
Jun 13, 2011, 10:51:38 PM6/13/11
to ggplot2
Next question on this example... if I reverse the order of the
plotting (i.e. the rectangles before the points), so that I don't have
to worry about the alpha issue (i.e. points on top of rectangles),
then I get the same error as I originally had (non-continuous variable
supplied to scale_x_continuous). I don't see what this should make a
difference.

Dennis Murphy

unread,
Jun 14, 2011, 3:15:07 AM6/14/11
to Scott N, ggplot2
Hi:

The problem is that x (FactorA) is a factor, so is not a continuous
variable. To precede geom_point() by geom_rect(), x has to be numeric
because you set xmin = 1 and ymin = 2. The error message doesn't occur
if geom_point() precedes geom_rect() because in that case, 1 is
associated with the first level of FactorA and 2 with the second level
of FactorA. In ggplot2, all the layers (and their scales) have to be
coordinated; usually, the order of layers doesn't matter that much,
but sometimes it does, and this is one such case, in large part
because you're trying to mix factors and numerics in the same scale.

One way around this is to make both x and y continuous scales. To do
this, we convert FactorA to numeric and use scale_x_continuous to
relabel at the appropriate values:

my.gg <- ggplot(mydata) + theme_bw(11) +

scale_y_continuous(breaks=c(2008,2009,2010,2011)) +
geom_rect(aes(xmin=1, xmax=2, ymin=2009.5, ymax=2010.25), fill="gray") +
geom_point(aes(as.numeric(FactorA), YearQtr, colour=FactorB), size=4) +


scale_color_manual(name="Group",values=c("darkolivegreen4","darkorange")) +

scale_x_continuous(breaks = 1:3, labels = c('Away', 'Home', 'Neutral')) +
labs(title = "View of Something Over Time", x = 'FactorA') +
opts(axis.text.x=theme_text(angle=90, hjust=1))
my.gg

HTH,
Dennis

Reply all
Reply to author
Forward
0 new messages