> # Additional remarks (which I am sure Hadley is well aware of, but just in
> case...):
>
> # 1/ bindiwdth does not work in the last construction of geom_bar, with
> stat="identity". I agree it does not make much sense when there is just one
> value but there should probably still be a way to control the width of the
> bar.
binwidth controls the binning performed by stat_bin, so you shouldn't
expect it to work when stat="identity". width should control the
physical width of the bars in that case.
> # 2/ The way to add error bars to such a bar chart kind of looks like a
> hack. Fortunately plyr makes it easy to compute the summary stats. But the
> use of stat="identity" with just one value seems "hacky" and the placement
> of the bars when width is specified (as emphasized here) is sub-optimal. I
> would expect that to be just an option in most of ggplot geoms, like
> errorbar=TRUE, or errorbar="sd"/"se"/"none"
I'm not completely sure what you're referring to here, but maybe the
examples in position_dodge will help with the alignment. There's no
built in support for calculating errors, mainly because there are so
many different ways to do it, depending on the underlying model.
Usually, it's easy enough to do with plyr, and then your calculations
are explicit, and easy to check.
> # 3/ there seem to be a quirk in the placement of bars in geom_bar:
> ggplot(datCounts) + geom_bar(aes(x=-depth, weight=abund, fill=class),
> binwidth=4) + scale_x_continuous(limits=c(-30,0)) + coord_flip()
> # --> bars correctly centered on 10 and 20
> ggplot(datCounts) + geom_bar(aes(x=-depth, weight=abund, fill=class),
> binwidth=2) + scale_x_continuous(limits=c(-30,0)) + coord_flip()
> # --> bars _starting_ on 10 and 20, but not centered while they could easily
> be since the binwidth is even.
The bars show the interval that the counts where binned over. For you
example, you could do
ggplot(datCounts) + geom_bar(aes(x=depth, fill=class), binwidth=2, origin = 1)
to have the bins centered on even numbers.
Hadley
On 2009-April-28 , at 14:16 , hadley wickham wrote:
> Unfortunately I don't have any ideas for the presentation, but I can
> at least answer these questions.
OK, too bad then. I guess the problem of this graph is really that it
tries to show too many things at once rather than some limitation in
the plotting program.
More generally, it seems that barcharts (and stacked barcharts in
particular) are most often used in histogram-like constructs, where
the height of the bars is proportional to the _sum_ of some counts, so
there is no variance involved in that, hence no need for error bars.
>> # 1/ bindiwdth does not work in the last construction of geom_bar,
>> with
>> stat="identity". I agree it does not make much sense when there is
>> just one
>> value but there should probably still be a way to control the width
>> of the
>> bar.
>
> binwidth controls the binning performed by stat_bin, so you shouldn't
> expect it to work when stat="identity". width should control the
> physical width of the bars in that case.
Indeed it was stupid of me to try binwidth since stat_bin is probably
not even called ;)
However, "width" is also an aesthetic of stat_bin, not of
stat_identity or geom_bar. So it should not work either. But it does.
In a strange way:
datCounts = data.frame(depth=c(rep(10,10), rep(20,10)),
class=rep(c(rep("<3",5), rep(">3",5)),2), abund=c(runif(10),
runif(10)*2))
datSummary = ddply(datCounts, .(depth, class), function(x){
data.frame(mean=mean(x$abund), sd=sd(x$abund))
})
# that does not work
ggplot(datSummary, aes(x=-depth)) + geom_bar(aes(y=mean, fill=class),
width=1, position="dodge", stat="identity") +
scale_x_continuous(limits=c(-30,0))
# but that works
ggplot(datSummary, aes(x=-depth)) + geom_bar(aes(y=mean, fill=class,
width=1), position="dodge", stat="identity") +
scale_x_continuous(limits=c(-30,0))
I would have expected "width" to be a parameter and not an aesthetic
in this case, since I fix it to a constant instead of mapping it to a
variable. I guess the difference is that, as an aesthetic, it gets
passed to the underlying stat function. But then, stat_identity does
not take any arguments...
>> # 2/ The way to add error bars to such a bar chart kind of looks
>> like a
>> hack. Fortunately plyr makes it easy to compute the summary stats.
>> But the
>> use of stat="identity" with just one value seems "hacky" and the
>> placement
>> of the bars when width is specified (as emphasized here) is sub-
>> optimal. I
>> would expect that to be just an option in most of ggplot geoms, like
>> errorbar=TRUE, or errorbar="sd"/"se"/"none"
>
> I'm not completely sure what you're referring to here, but maybe the
> examples in position_dodge will help with the alignment.
I am referring to the fact that, when width is not the same in
geom_bar and geom_errorbar the error bars are not centered on the bar.
This is the case when "width" is specified in either geom_bar or
geom_errorbar with a value different from the default, or in both but
with different values.
p= ggplot(datSummary, aes(x=-depth)) +
geom_bar(aes(y=mean, fill=class, width=4), position="dodge",
stat="identity") +
scale_x_continuous(limits=c(-30,0))
p + geom_errorbar(aes(ymax=(mean+sd),ymin=(mean-sd)), width=2,
position="dodge")
Indeed the doc for position_dodge helps and this works:
p + geom_errorbar(aes(ymax=(mean+sd),ymin=(mean-sd)), width=2,
position=position_dodge(width=4))
My problem probably came from not realizing that errorbar is a geom in
itself, completely independent of whatever you draw underneath. So, if
I want the two layers to match, I have to deal with the placement
myself. I guess I was spoiled by the rest of ggplot which usually
deals with this kind of graphical alignment for you. Plus, error bars
are rarely drawn by themselves. Conceptually, they often complement
another geom rather than being a geom per se. So one could expect them
to be automatically aligned to whatever they complement.
I am probably still not very clear...
NB: setting the width parameter as a general aesthetic in the ggplot
call helps synchronizing all the widths:
ggplot(datSummary, aes(x=-depth, width=6)) +
geom_bar(aes(y=mean, fill=class), position="dodge", stat="identity") +
scale_x_continuous(limits=c(-30,0)) +
geom_errorbar(aes(ymax=(mean+sd),ymin=(mean-sd)), position="dodge")
> There's no
> built in support for calculating errors, mainly because there are so
> many different ways to do it, depending on the underlying model.
> Usually, it's easy enough to do with plyr, and then your calculations
> are explicit, and easy to check.
OK, fair enough (I need to learn plyr anyway ;) )
>> # 3/ there seem to be a quirk in the placement of bars in geom_bar:
>> ggplot(datCounts) + geom_bar(aes(x=-depth, weight=abund, fill=class),
>> binwidth=4) + scale_x_continuous(limits=c(-30,0)) + coord_flip()
>> # --> bars correctly centered on 10 and 20
>> ggplot(datCounts) + geom_bar(aes(x=-depth, weight=abund, fill=class),
>> binwidth=2) + scale_x_continuous(limits=c(-30,0)) + coord_flip()
>> # --> bars _starting_ on 10 and 20, but not centered while they
>> could easily
>> be since the binwidth is even.
>
> The bars show the interval that the counts where binned over. For you
> example, you could do
>
> ggplot(datCounts) + geom_bar(aes(x=depth, fill=class), binwidth=2,
> origin = 1)
>
> to have the bins centered on even numbers.
Thanks. It works.
JiHO
---
http://jo.irisson.free.fr/
Yes, this is technically a bug, but it's hard to fix and it crops up
so rarely that I haven't bothered - width is tricky because it
indirectly affects the range of the x axis.
> My problem probably came from not realizing that errorbar is a geom in
> itself, completely independent of whatever you draw underneath. So, if I
> want the two layers to match, I have to deal with the placement myself. I
> guess I was spoiled by the rest of ggplot which usually deals with this kind
> of graphical alignment for you. Plus, error bars are rarely drawn by
> themselves. Conceptually, they often complement another geom rather than
> being a geom per se. So one could expect them to be automatically aligned to
> whatever they complement.
Yes, each layer is completely independent from the others that come
before it, which means that you do need to align them yourself. It's
very hard to do this in general, and I'm pretty certain it would end
up being a nuisance in other circumstances.
Regards,
Hadley