fine tuning of my first ggplot2 plot

118 views
Skip to first unread message

MatthieuDubois

unread,
Jun 10, 2009, 4:59:08 AM6/10/09
to ggplot2
Dear all,

first of all, please excuse me for the possibly basic question I have
and the poor subject of the thread.

I'm currently starting to use ggplot2 and attempts to tune a plot for
publication. It is a scatter plot representing performance of control
participants vs. brain damaged patients, with a lm regression line for
controls only, along with a 95% prediction confidence interval and a
dotted line corresponding to a probability of 0.05 of the distribution
of predicting a new score on the basis of the lm.

The following code do almost what I want. I just would like to
(1) change the colours for the groups (control would be blue and
patient would be red)
(2) modify the legend in order to reflect that the regression line and
confidence intervals are computed only for the 'control' group
(current legend shows a regression line and dashed area for both
groups) and
(3) add the regression equation above the legend.

Any help would be appreciated. And thanks a lot for this beautiful
package.

Regards,

Matthieu


## CODE:
library(ggplot2)

# generate some data
# group is a two level factor 'control' for normal participants;
'patient' for brain-damaged people
# the effect of the lesion is simulated in y by setting subtracting 2
on the 'y' value
x <- rnorm(100)
group <- factor(rbinom(x, size=1, p=0.2), labels=c('control',
'patient'))
y <- 1.3*x + 3 + ifelse(group=='control', 0, -2) + rnorm(x, sd=1)
final <- data.frame(group,x,y)

# initial plot
ppred <- qplot(x=x, y=y, colour=group, data=final)

# compute the regression for control subjects only
model <- lm(y~x, data=final, subset=group=='control')

# compute the predicted values for the confidence interval and the
dotted line, using predict
pred.grid <- with(final, expand.grid(
x=seq(min(x), max(x), length=101),
group='control'))
pred <- predict(model, newdata=pred.grid,interval=('prediction'))
pred <- data.frame(pred.grid,pred)
# select only the lower values of a confidence interval (level=0.9),
which corresponds to the lower 5%
pred$lwr.9 <- predict(model, newdata=pred,interval=('prediction'),
level=0.9)[,2]

# add layers to plot
ppred + geom_smooth(aes(y=fit, ymin=lwr, ymax=upr), data=pred,
stat='identity') + geom_line(aes(y=lwr.9), data=pred, linetype=2,
colour="grey40")



Matthieu Dubois
Post-doctoral fellow

Psychology and NeuroCognition Lab (CNRS UMR 5105)
Université Pierre Mendès-France
BP47 --- 38040 Grenoble Cedex 9 --- France



baptiste auguie

unread,
Jun 10, 2009, 7:34:07 AM6/10/09
to MatthieuDubois, ggplot2
the colour is simple,

p <- last_plot() +
scale_colour_manual(values=c("#377EB8","#E41A1C")) # or "red" and
"blue", i prefer these

You can add an equation using Grid,

grob <- ggplotGrob(p)
grob <- addGrob(grob, textGrob(x = unit(0.9, "npc"), y = unit(0.7,
"npc"),label=expression(alpha^2),
gp = gpar(col = "red")))
grid.draw(grob)

but the legend seems more tricky. Hopefully someone will come up with
a solution.

HTH,

baptiste
--
_____________________________

Baptiste Auguié

School of Physics
University of Exeter
Stocker Road,
Exeter, Devon,
EX4 4QL, UK

http://newton.ex.ac.uk/research/emag
______________________________

Peter Flom

unread,
Jun 10, 2009, 7:44:29 AM6/10/09
to baptiste auguie, MatthieuDubois, ggplot2
baptiste auguie <bapt...@googlemail.com> wrote

>but the legend seems more tricky. Hopefully someone will come up with
>a solution.


This is probably my least favorite part of ggplot - that is, the lack of control over
the legend. USUALLY the program gets it right. But it's very hard to modify.

Peter

Peter L. Flom, PhD
Statistical Consultant
www DOT peterflomconsulting DOT com

hadley wickham

unread,
Jun 10, 2009, 9:16:55 AM6/10/09
to Peter Flom, baptiste auguie, MatthieuDubois, ggplot2
>>but the legend seems more tricky. Hopefully someone will come up with
>>a solution.
>
> This is probably my least favorite part of ggplot - that is, the lack of control over
> the legend.  USUALLY the program gets it right.  But it's very hard to modify.

It's my believe that it should almost always be possible to
programmatically determine the correct legend. If you have any
counter examples, I'd like to see them.

Unfortunately, this case is one I had not anticipated, so currently
can't see anyway to show the smooth on just one of the points on the
legend.

Hadley


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

baptiste auguie

unread,
Jun 10, 2009, 9:19:50 AM6/10/09
to MatthieuDubois, ggplot2
Below is an ugly hack to remove the segment altogether from the legend
(hoping the colour coding would be enough). It's probably not
something to recommend, let's hope a better way is suggested to you,

library(ggplot2)

x <- rnorm(100)
group <- factor(rbinom(x, size=1, p=0.2), labels=c('control','patient'))
y <- 1.3*x + 3 + ifelse(group=='control', 0, -2) + rnorm(x, sd=1)
final <- data.frame(group,x,y)

# compute the regression for control subjects only
model <- lm(y~x, data=final, subset=group=='control')

# compute the predicted values for the confidence interval and the

# dotted line, using predict

pred.grid <- with(final, expand.grid(
x=seq(min(x), max(x), length=101),
group='control'))
pred <- predict(model, newdata=pred.grid,interval=('prediction'))
pred <- data.frame(pred.grid,pred)

# select only the lower values of a confidence interval (level=0.9),

# which corresponds to the lower 5%


pred$lwr.9 <- predict(model, newdata=pred,interval=('prediction'),level=0.9)[,2]


p <- ggplot(data = final, mapping = aes(x = x, y = y, fill=group)) +


geom_smooth(aes(y=fit, ymin=lwr, ymax=upr), data=pred, stat='identity') +

geom_line(aes(y=lwr.9), data=pred, linetype=2, colour="grey40")+
geom_point(aes(colour=group))+
scale_colour_manual(values=c("#377EB8","#E41A1C")) +
scale_fill_manual(values=c("#377EB8", NA))


GeomSmooth$draw_legend <- function (., data, params, ...)
{
data <- aesdefaults(data, .$default_aes(), list(...))
data$fill <- alpha(data$fill, data$alpha)
rectGrob(gp = gpar(col = NA, fill = data$fill))

}

p
# reload the default one
detach(package:ggplot2, unload=T)
library(ggplot2)

# p # usual behavior

Peter Flom

unread,
Jun 10, 2009, 9:33:07 AM6/10/09
to hadley wickham, ggplot2
hadley wickham <h.wi...@gmail.com> wrote

>It's my believe that it should almost always be possible to
>programmatically determine the correct legend. If you have any
>counter examples, I'd like to see them.
>


OK, here's one I am having some trouble with .... excuse the length ....the idea
is to compare how Obama did and how Kerry did in different congressional districts,
using LM.

# FIRST, I SET UP THE DATA

library(foreign)
library(ggplot2)
origdata <- read.csv("c:/personal/dailykos/blackrepdem.csv")
state <- substr(origdata$district, 1, 2)
southern <- state == 'AL' | state == 'AR' | state == 'FL' | state == 'GA' | state == 'LA'|
state == 'MS' | state == 'NC' | state == 'SC'| state == 'TN' | state == 'VA'
party <- substr(origdata$Party,2,2)

testdata <- expand.grid(southern = c(TRUE, FALSE), Black = seq(0, 65, by = 10))

#NEXT, THE OBAMA EQUATION

ObamaRegionBlack <- with(origdata, ols(Obama~southern*Black))

Obamapredicted <- predict(ObamaRegionBlack, testdata)
Obamaprediction <- data.frame(cbind(testdata, Obamapredicted))

# AND A PLOT

plot2 <- qplot(data = Obamaprediction, Black, Obamapredicted, colour = southern,
main = "Obama vote predicted by region and pct Black.",
xlab = 'Percent Black',
ylab = 'Predicted Obama vote')

plot2 <- plot2 + geom_line() + aes(colour = southern) + scale_colour_manual(value = c("red", "blue"))


# SAME THING FOR KERRY
KerryRegionBlack <- with(origdata, ols(Kerry~southern*Black))

Kerrypredicted <- predict(KerryRegionBlack, testdata)
Kerryprediction <- data.frame(cbind(testdata, Kerrypredicted))

plot3 <- qplot(data = Kerryprediction, Black, Kerrypredicted, colour = southern,
main = "Kerry vote Kerrypredicted by region and pct Black.",
xlab = 'Percent Black',
ylab = 'Predicted Kerry vote')

plot3 <- plot3 + geom_line() + aes(colour = southern) + scale_colour_manual(value = c("red", "blue"))

# AND THOSE TWO ARE GOOD. JUST HOW I WOULD WANT THEM

# BUT TO COMBINE THEM?????? HERE'S WHAT I DID, BUT, WHILE IT'S OK IT ISN'T GREAT AT ALL
plot4 <- qplot(data = Kerryprediction, Black, Kerrypredicted, colour = southern,
main = "Kerry and Obama vote Kerrypredicted by region and pct Black.",
xlab = 'Percent Black',
ylab = 'Predicted Democratic vote',
ylim = c(30, 100))

plot4 <- plot4 + geom_line() + aes(colour = southern) + scale_colour_manual(value = c("red", "blue"))


plot4 <- plot4 + geom_abline(intercept = 49.42, slope = 0.682, colour = 'blue', linetype = 2)
plot4 <- plot4 + geom_abline(intercept = 49.42-13.88, slope = 0.682-.129, colour = 'red', linetype = 2)


####################
I can send the data sets, if need be.


TIA

Kasper Daniel Hansen

unread,
Jun 10, 2009, 11:39:35 AM6/10/09
to MatthieuDubois, ggplot2
For the legend, post-process in a vecotr graphics program like
Inkscape or Adobe Illustrator.

Kasper

Peter Flom

unread,
Jun 10, 2009, 3:49:14 PM6/10/09
to Felipe Carrillo, ggplot2group
Felipe

It is attached. It's actually only one data set.


Peter

-----Original Message-----
>From: Felipe Carrillo <mazatla...@yahoo.com>
>Sent: Jun 10, 2009 10:12 AM
>To: Peter Flom <peterflom...@mindspring.com>
>Subject: Re: fine tuning of my first ggplot2 plot
>
>
>Peter:
>Would you mind sending the datasets?
>
>
>Felipe D. Carrillo
>Supervisory Fishery Biologist
>Department of the Interior
>US Fish & Wildlife Service
>California, USA
>
>
>--- On Wed, 6/10/09, Peter Flom <peterflom...@mindspring.com> wrote:
BlackRepDem.csv

hadley wickham

unread,
Jun 17, 2009, 5:52:16 PM6/17/09
to Peter Flom, ggplot2
On Wed, Jun 10, 2009 at 8:33 AM, Peter
Flom<peterflom...@mindspring.com> wrote:
> hadley wickham <h.wi...@gmail.com> wrote
>
>>It's my believe that it should almost always be possible to
>>programmatically determine the correct legend.  If you have any
>>counter examples, I'd like to see them.
>>
>
>
> OK, here's one I am having some trouble with .... excuse the length ....the idea
> is to compare how Obama did and how Kerry did in different congressional districts,
> using LM.

Conceptually, you need to combine Obamaprediction and Kerryprediction
into a single data frame, adding a variable that differentiates
between the two, and using the same variable for the y axis. Then you
can do something like:

ggplot(both, aes(percent_black, prediction, colour = southern,
linetype = president)) +
geom_line()

(Assuming I'm guessing correctly what you want)

Hadley

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

Reply all
Reply to author
Forward
0 new messages