Space free on one axis only

68 views
Skip to first unread message

Tine Casneuf

unread,
Nov 23, 2011, 4:01:55 AM11/23/11
to ggplot2
Hi all,

Is there a way to do space free for 1 axis only? Using the dummy plot
code below, you can see that i have a population of 34 animals,
assigned into 2 categories, group X or Y, and 2 measurements A and B
on these animals.

Because group X contains many more animals, the bars per animal are
much more narrow than those of group Y. I therefore used space =
"free", but the problem is that the B measurements are squeezed to
such an extent that the axis and values are not interpretable any
more.

Many thanks in advance!
Best,
tine

####
Animal <- paste("Anim", 1:34, sep = "")
xx <- data.frame(Animal, Value = c(sample(1:10, 17, replace = TRUE),
sample(1:2, 17, replace = TRUE)/5),
group = rep(c(rep("X", 15), rep ("Y", 2)),2), measurement =
c(rep("measurm A",17), rep ("measurm B", 17)), stringsAsFactors =
FALSE)
p <- ggplot(data = xx, aes(x = Animal, y = Value))
p <- p + geom_bar(stat = "identity")
p <- p + facet_grid(measurement ~ group, scales = "free")
p <- p + opts(title = "Option Space Fixed")
print(p)


q <- ggplot(data = xx, aes(x = Animal, y = Value))
q <- q + geom_bar(stat = "identity")
q <- q + facet_grid(measurement ~ group, scales = "free", space =
"free")
q <- q + opts(title = "Option Space Free")
print(q)

Dennis Murphy

unread,
Nov 23, 2011, 3:12:27 PM11/23/11
to Tine Casneuf, ggplot2
Hi:

If you look at the help page http://had.co.nz/ggplot2/facet_grid.html,
you'll discover 'free_x' and 'free_y' options for the scales =
argument in facet_grid(). See the examples toward the bottom of the
help page for illustration.

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
>

Tine Casneuf

unread,
Nov 24, 2011, 5:35:08 AM11/24/11
to Dennis Murphy, ggplot2
Hi Dennis,

thanks for your reply. I implemented it this way:

q <- ggplot(data = xx, aes(x = Animal, y = Value))
q <- q + geom_bar(stat = "identity")
q <- q + facet_grid(measurement ~ group, scales = "free_x", space =
        "free")
q <- q + opts(title = "Option Space Free")
print(q)

Close to what i was looking for, but  the Yaxis is not free scaled in this case. The values of the bottom plots are not interpretable this way. Also scales = "free_y" or scales = "free" don't get the job done. 

Any other suggestions? 

Best wishes,

tine

Brandon Hurr

unread,
Nov 24, 2011, 5:46:26 AM11/24/11
to Tine Casneuf, Dennis Murphy, ggplot2
I'm not entirely sure what you're after regarding the appearance of
the x and y axis (scale-wise), but I did the following and it improved
the readability of the x-axis text...

ggplot(data = xx, aes(x = Animal, y = Value))+
geom_bar(stat = "identity")+
facet_grid(measurement ~ group, scales = "free_x", space ="free")+
opts(title = "Option Space Free", axis.text.x = theme_text(angle =
270, hjust=0, vjust=0.5))

Tine Casneuf

unread,
Nov 24, 2011, 6:29:35 AM11/24/11
to Brandon Hurr, Dennis Murphy, ggplot2
Hi guys,

First of all, thanks for the suggestions. The labels on the X are better like that, but that was not what i am after.

I'll try to explain again. Looking at this plot:
Animal <- paste("Anim", 1:34, sep = "")
xx <- data.frame(Animal, Value = c(sample(1:10, 17, replace = TRUE),
        sample(1:2, 17, replace = TRUE)/5),
    group = rep(c(rep("X", 15), rep ("Y", 2)),2), measurement =
        c(rep("measurm A",17), rep ("measurm B", 17)), stringsAsFactors =
        FALSE)
p <- ggplot(data = xx, aes(x = Animal, y = Value))
p <- p + geom_bar(stat = "identity")
p <- p + facet_grid(measurement ~ group, scales = "free")
print(p)

The scale of the Yaxis is fine (0 -> 10 top and 0 -> 0.4 bottom), but because there are more animals in group X than Y, the difference in width of the bars looks silly. I succeeded in fixing that by adding in space = "free"

q <- ggplot(data = xx, aes(x = Animal, y = Value))
q <- q + geom_bar(stat = "identity")
q <- q + facet_grid(measurement ~ group, scales = "free", space = "free")
print(q)

However for this plot, the Y axis are scaled too, so that the bottom plot is squeezed. 

Ideally i would like the X axis of the 2nd plot and the Y axis of the 1st one. Which is why i was wondering if it is possible to get space = "free_x" and not for Y in this case.

Thanks again,

tine

Brandon Hurr

unread,
Nov 24, 2011, 6:42:08 AM11/24/11
to Tine Casneuf, Dennis Murphy, ggplot2
I think I understand now. As far as I can tell you cannot specify a single axis to be free and not the other.

You try and specify it and you get the following:
Error in match.arg(space, c("fixed", "free")) :
 'arg' should be one of “fixed”, “free”


It might be possible, but someone with knowledge of the guts would know better for sure.

B
scal.frx.spce.free.png
scal.free.spce.fix.png

Johannes Radinger

unread,
Nov 24, 2011, 7:33:28 AM11/24/11
to Brandon Hurr, tineke....@gmail.com, ggp...@googlegroups.com, djm...@gmail.com
Hi,

I also don't think that it is possible at the moment to
change axis for only one plot in a facett wrap.
I am also interested in a solution: My problem is that
I wanted free scales for my x but some of them with a log
scale and some without. I think that is a similar
problem like yours.

Hopefully that feature will be implemented some time.

/Johannes

--
NEU: FreePhone - 0ct/min Handyspartarif mit Geld-zurück-Garantie!
Jetzt informieren: http://www.gmx.net/de/go/freephone

Dennis Murphy

unread,
Nov 24, 2011, 8:31:00 AM11/24/11
to Tine Casneuf, Brandon Hurr, ggplot2
If you want independent scales in each facet, you're going to have to
use another approach. For example, you could make four independent
plots and then render them in a 2 x 2 arrangement using the grid
package and its layout features. [You need grid because ggplot2 is
based on grid graphics.] An alternative is to use the grid.arrange()
function in the gridExtra package. The example below uses the former
approach, illustrated on p. 154 of the ggplot2 book.

Moreover, I'm wondering why you would want to use a bar chart to plot
values. Bar charts are intended to visualize discrete distributions -
any other use of that visual metaphor is, IMO, senseless. It wastes
ink and obscures patterns. Why aren't you using line plots for this
instead? They consume less ink and do a better job of telling the
story (i.e., they have a higher information-to-ink ratio). Here's one
way to do it. I chose to split the data frames so that there was one
data frame per plot, but strictly speaking, this isn't necessary.

# This violates the DRY principle (don't repeat yourself)
# I'm making an exception for this purpose
ds1 <- subset(xx, group == 'X' & measurement == 'measurm A')
ds2 <- subset(xx, group == 'X' & measurement == 'measurm B')
ds3 <- subset(xx, group == 'Y' & measurement == 'measurm A')
ds4 <- subset(xx, group == 'Y' & measurement == 'measurm B')

# Create a numeric vector to use as the x-axis values in each plot
ds1$anim <- seq_len(nrow(ds1))
ds2$anim <- seq_len(nrow(ds2))
ds3$anim <- seq_len(nrow(ds3))
ds4$anim <- seq_len(nrow(ds4))

p1 <- ggplot(ds1, aes(anim, Value)) + geom_point() + geom_line() +
labs(x = '') + ylim(0, 10) +
opts(title = 'Gp: X Meas: A',
plot.title = theme_text(size = 10)) +
scale_x_continuous(breaks = ds1$anim,
labels = sapply(ds1$Animal, function(s) substr(s, 5, 6)))
p2 <- ggplot(ds2, aes(anim, Value)) + geom_point() + geom_line() +
scale_x_continuous(breaks = ds2$anim,
labels = sapply(ds2$Animal, function(s) substr(s, 5, 6))) +
labs(x = 'Animal') + ylim(0, 0.4) +
opts(title = 'Gp: X Meas: B',
axis.title.x = theme_text(size = 9),
plot.title = theme_text(size = 10))
p3 <- ggplot(ds3, aes(anim, Value)) + geom_point() + geom_line() +
scale_x_continuous(breaks = ds3$anim,
labels = sapply(ds3$Animal, function(s) substr(s, 5, 6))) +
labs(x = "", y = "") + ylim(0, 10) +
opts(title = 'Gp: Y Meas: A',
axis.text.y = theme_blank(),
plot.title = theme_text(size = 10),
plot.background = theme_blank())
p4 <- ggplot(ds4, aes(anim, Value)) + geom_point() + geom_line() +
scale_x_continuous(breaks = ds4$anim,
labels = sapply(ds4$Animal, function(s) substr(s, 5, 6))) +
labs(x = 'Animal', y = "") + ylim(0, 0.4) +
opts(title = 'Gp: Y Meas: B',
plot.title = theme_text(size = 10),
axis.text.y = theme_blank(),
axis.title.x = theme_text(size = 9),
plot.background = theme_blank())

library('grid')

vplayout <- function(x, y)
viewport(layout.pos.row = x, layout.pos.col = y)

grid.newpage()
pushViewport(viewport(layout = grid.layout(100, 100)))

print(p1, vp = vplayout(1:50, 1:85))
print(p3, vp = vplayout(1:50, 81:100))
print(p2, vp = vplayout(51:100, 1:85))
print(p4, vp = vplayout(51:100, 81:100))


Alternatively, you could order the animals by increasing value if that
was meaningful - the simplest way to do this would be to add a
character variable to each of the split data frames corresponding to
the animal number as I did in the sapply() function, use the arrange()
function in plyr or order() in base to order the rows by value and
then plot.

It's not necessary to split the data frames as I did here - you could
do all this in the plyr package with a little effort and then use
subset() for the individual plots. Because you wanted different x/y
scales in different panels, you have to go this route.

I inserted enough elements here for you to play with and tweak to your choice.

HTH,
Dennis

Kohske Takahashi

unread,
Nov 24, 2011, 7:40:47 PM11/24/11
to Dennis Murphy, Tine Casneuf, Brandon Hurr, ggplot2
Hi,
I think these options are useful.

Perhaps, the definition of `facet_*` will be like this:
facet_grid(..., space = "fixed", space.x = space, space.y = space, ...)

Hadley, do you have any plan to implement these functionality in the
future release?
Also, I noticed that `widths` and `heights` args is missing in the dev
branch. Is this designed?
https://github.com/hadley/ggplot2/blob/develop/R/facet-grid-.r

kohske

--
Kohske Takahashi <takahash...@gmail.com>

Research Center for Advanced Science and Technology,
The University of  Tokyo, Japan.
http://www.fennel.rcast.u-tokyo.ac.jp/profilee_ktakahashi.html

2011/11/24 Dennis Murphy <djm...@gmail.com>:

Brandon Hurr

unread,
Nov 25, 2011, 3:16:16 AM11/25/11
to Kohske Takahashi, Dennis Murphy, Tine Casneuf, ggplot2
I can see how it could be useful to have space be free by axis rather than all or nothing. Add me to the pile of requestors. 

Brandon

Hadley Wickham

unread,
Dec 1, 2011, 11:08:38 AM12/1/11
to Kohske Takahashi, Dennis Murphy, Tine Casneuf, Brandon Hurr, ggplot2
> Hadley, do you have any plan to implement these functionality in the
> future release?
> Also, I noticed that `widths` and `heights` args is missing in the dev
> branch. Is this designed?
> https://github.com/hadley/ggplot2/blob/develop/R/facet-grid-.r

I think they're desirable features, but they are fiddly to implement,
and I don't really have any idea of what the syntax should look like.

Hadley

--
Assistant Professor / Dobelman Family Junior Chair
Department of Statistics / Rice University
http://had.co.nz/

Willem

unread,
Dec 22, 2011, 7:42:47 AM12/22/11
to ggplot2
I have just added support for free_x and free_y to the space argument
of facet_grid.
You can give it a try from my github version:
https://github.com/wligtenberg/ggplot2

@Hadley maybe this could be merged in for 0.9, or am I too late?

Kind regards,

Willem
Message has been deleted

Hadley Wickham

unread,
Dec 23, 2011, 9:08:39 AM12/23/11
to Willem, ggplot2
> @Hadley maybe this could be merged in for 0.9, or am I too late?

It's possible - I still probably have a few days worth of
documentation work to do.

A few comments:

* Can you please move future discussion to ggplot-dev?

* Can you please generate a pull request? That makes it easier to
comment on your changes. Generally, it's best to do anything in a
branch so it's easier to keep in sync with main development.

* You'll also need to update the documentation (including a couple of
examples) and add a note to NEWS about the change

Reply all
Reply to author
Forward
0 new messages