Combination plot: bar + line plot with their respective y-axis on opposite sides

39 views
Skip to first unread message

Sawfoot

unread,
Feb 17, 2009, 4:46:56 AM2/17/09
to ggplot2
I was wondering if ggplot2 can do something like this:

http://users.fmg.uva.nl/rgrasman/rpages/2005/08/combination-plot-bar-line-plot-with_05.html

I found their method a bit convoluted but couldn't find anything
similar in the ggplot book of plotting separate datasets with
different scales on the same graph. Addition of geom_errorbar would
also be nice.

Thanks,

Shane

David Hajage

unread,
Feb 17, 2009, 5:04:04 AM2/17/09
to Sawfoot, ggplot2
Hadley has probably a better answer, but I think the answer is no.

The big problem is : "plot with their respective y-axis on opposite sides". See here : http://tolstoy.newcastle.edu.au/R/e5/help/08/11/7405.html

"Unfortunately, the capability is currently unavailable in ggplot2 and is unlikely to ever be available because I believe it is a fundamentally inaccurate means of presenting data. However, in the next version it will be much easier to created faceted displays with varying scales, which should be a better solution for many of these types of problems. "

David

hadley wickham

unread,
Feb 17, 2009, 9:04:01 AM2/17/09
to David Hajage, Sawfoot, ggplot2
On Tue, Feb 17, 2009 at 4:04 AM, David Hajage <dha...@gmail.com> wrote:
> Hadley has probably a better answer, but I think the answer is no.
>
> The big problem is : "plot with their respective y-axis on opposite sides".
> See here : http://tolstoy.newcastle.edu.au/R/e5/help/08/11/7405.html
>
> "Unfortunately, the capability is currently unavailable in ggplot2 and is
> unlikely to ever be available because I believe it is a fundamentally
> inaccurate means of presenting data. However, in the next version it will be
> much easier to created faceted displays with varying scales, which should be
> a better solution for many of these types of problems. "

Exactly right :) However, that's not actually needed for this chart:
note that the scales hardly overlap so you don't lose anything but
having two separate plots on top of each other.

# Restructure data into a single data frame
RT = matrix(c(814, 500, 424, 394, 967, 574, 472, 446),4,2)
colnames(RT) = c('repetition','alternation')
rownames(RT) = c('7-yrs','11-yrs','15-yrs','21-yrs')

library(ggplot2)
rt <- melt(RT)
names(rt) <- c("age", "trt", "value")
rt$variable <- "rt"

errors <- melt(as.matrix(error))
names(errors) <- c("age", "trt", "value")
errors$variable <- "error"

df <- rbind(rt, errors)

# Make sure factors are ordered correctly
df$age <- factor(df$age, levels = c("7-yrs", "11-yrs", "15-yrs", "21-yrs"))

# Which results in:
structure(list(age = structure(c(1L, 2L, 3L, 4L, 1L, 2L, 3L,
4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L), .Label = c("7-yrs", "11-yrs",
"15-yrs", "21-yrs"), class = "factor"), trt = structure(c(2L,
2L, 2L, 2L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 1L, 1L, 1L, 1L), .Label =
c("alternation",
"repetition"), class = "factor"), value = c(814, 500, 424, 394,
967, 574, 472, 446, 10, 6, 6, 4, 13, 7, 6, 3), variable = c("rt",
"rt", "rt", "rt", "rt", "rt", "rt", "rt", "error", "error", "error",
"error", "error", "error", "error", "error")), .Names = c("age",
"trt", "value", "variable"), row.names = c(NA, 16L), class = "data.frame")

# It's now straightforward to create recreate the plot with lines
# or with bars:

plot <- ggplot(df, aes(age, value, colour = trt, fill = trt)) +
facet_grid(variable ~ . , scale = "free")

plot + geom_bar(position = "dodge")
plot + geom_line(aes(group = trt)) + geom_point()

# It's then just a matter of combining the two:
plot +
geom_bar(position = "dodge", data = subset(df, variable == "rt")) +
geom_line(aes(group = trt), data = subset(df, variable == "error"))
# Unfortunately this currently results in an error, which
# I've added to my to do list to fix


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

Mike Lawrence

unread,
Feb 17, 2009, 9:18:02 AM2/17/09
to hadley wickham, David Hajage, Sawfoot, ggplot2
Hadley's example neglected to create the object "error" at the outset,
so I encountered other problems with it. Here is what I presume Hadley
meant:

library(ggplot2)

RT = matrix(c(814, 500, 424, 394, 967, 574, 472, 446),4,2)
colnames(RT) = c('repetition','alternation')
rownames(RT) = c('7-yrs','11-yrs','15-yrs','21-yrs')

rt <- melt(RT)


names(rt) <- c("age", "trt", "value")
rt$variable <- "rt"

#this next block was missing in Hadley's previous example
error = matrix(c(10,6,6,4,13,7,6,3),4,2)
colnames(error) = c('repetition','alternation')
rownames(error) = c('7-yrs','11-yrs','15-yrs','21-yrs')

errors <- melt(error)


names(errors) <- c("age", "trt", "value")
errors$variable <- "error"

df <- rbind(rt, errors)

# Make sure factors are ordered correctly
df$age <- factor(df$age, levels = c("7-yrs", "11-yrs", "15-yrs", "21-yrs"))

# Which results in:
structure(list(age = structure(c(1L, 2L, 3L, 4L, 1L, 2L, 3L,
4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L), .Label = c("7-yrs", "11-yrs",
"15-yrs", "21-yrs"), class = "factor"), trt = structure(c(2L,
2L, 2L, 2L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 1L, 1L, 1L, 1L), .Label =
c("alternation",
"repetition"), class = "factor"), value = c(814, 500, 424, 394,
967, 574, 472, 446, 10, 6, 6, 4, 13, 7, 6, 3), variable = c("rt",
"rt", "rt", "rt", "rt", "rt", "rt", "rt", "error", "error", "error",
"error", "error", "error", "error", "error")), .Names = c("age",
"trt", "value", "variable"), row.names = c(NA, 16L), class = "data.frame")

# It's now straightforward to create recreate the plot with lines
# or with bars:

plot <- ggplot(df, aes(x=age, y=value, colour = trt, fill = trt)) +

Sawfoot

unread,
Feb 17, 2009, 9:57:03 AM2/17/09
to ggplot2
That is great. In regard to the error bars I mentioned, I got to add
them with:

se = c(12, 20, 20, 15, 20, 19, 20,10, .5, 1, .9, 1.5, 1, 1.3, 0.5,
1.1)
df <- cbind(df, se)

dodge <- position_dodge(width = 0.9)
plot + geom_bar(position = "dodge") + geom_errorbar(aes(min = value -
se, max = value + se),width = 0.2, size = 1.4, position = dodge )

plot + geom_line(aes(group = trt)) + geom_point() + geom_errorbar(aes
(min = value - se, max = value + se),width = 0.2)

But I tried to use dodge with geom_point (a few different ways) but I
couldn't get it to work

e.g.

plot + geom_point(position = "dodge") + geom_line(aes(group = trt)) +
geom_errorbar(aes(min = value - se, max = value + se),width = 0.2,
position = "dodge")

What I am doing wrong?

Sawfoot

unread,
Feb 18, 2009, 7:29:50 AM2/18/09
to ggplot2
Ok, figured it out:

dodge <- position_dodge(width = 0.3)
plot + geom_point(position = dodge ) + geom_line(aes(group =
Condition), position = dodge) + geom_errorbar(aes(min = value - se,
max = value + se),width = 0.2, size=1.05, position = dodge)

Though I think dodged lines are confusing so it looks better without
the geom_line when using error bars.

Is there any way to control the formatting of different facet axes so
to label different scales? My clunky solution for titling the y axis
on the RT and errors plot is to have spaces between the headings as
below:

last_plot() + scale_y_continuous(vjust = 5,hjust = .5, "RT
(ms) Errors %")


On Feb 17, 2:57 pm, Sawfoot <shane.lind...@gmail.com> wrote:
> That is great. In regard to the error bars I mentioned, I got to add
> them with:
>
> se = c(12, 20, 20, 15, 20, 19, 20,10, .5, 1, .9, 1.5, 1, 1.3, 0.5,
> 1.1)
> df <- cbind(df, se)
>
> dodge <- position_dodge(width = 0.9)
> plot + geom_bar(position = "dodge") + geom_errorbar(aes(min = value -
> se, max = value + se),width = 0.2, size = 1.4, position = dodge )
>
> plot + geom_line(aes(group = trt)) + geom_point() + geom_errorbar(aes
> (min = value - se, max = value + se),width = 0.2)
>
> But I tried to use dodge with geom_point (a few different ways) but I
> couldn't get it to work
>
> e.g.
>
> plot + geom_point(position = "dodge") + geom_line(aes(group = trt)) +
> geom_errorbar(aes(min = value - se, max = value + se),width = 0.2,
> position = "dodge")
>
> What I am doing wrong?
>

hadley wickham

unread,
Feb 18, 2009, 9:27:09 AM2/18/09
to Sawfoot, ggplot2
On Wed, Feb 18, 2009 at 6:29 AM, Sawfoot <shane....@gmail.com> wrote:
>
> Ok, figured it out:
>
> dodge <- position_dodge(width = 0.3)
> plot + geom_point(position = dodge ) + geom_line(aes(group =
> Condition), position = dodge) + geom_errorbar(aes(min = value - se,
> max = value + se),width = 0.2, size=1.05, position = dodge)
>
> Though I think dodged lines are confusing so it looks better without
> the geom_line when using error bars.
>
> Is there any way to control the formatting of different facet axes so
> to label different scales? My clunky solution for titling the y axis
> on the RT and errors plot is to have spaces between the headings as
> below:
>
> last_plot() + scale_y_continuous(vjust = 5,hjust = .5, "RT
> (ms) Errors %")
>

Not at the moment. I have some changes further down in the pipeline
that should make this easier.

Hadley

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

Reply all
Reply to author
Forward
0 new messages