4

could you tell me if it is possible make a bar plot with bar height normalized to 1, but bar width proportional to the number of elements in each bin.

Example : this plot

ggplot(mtcars, aes(x=factor(cyl), fill=factor(vs))) + geom_bar(position="fill")

and then make the width of the 3 bars proportional to

table(factor(mtcars$cyl))

There is well that "width" parameter in position_fill() but it has to be a constant, hasn't it ?

Thank you,

François

EDIT :

I tried a bit further, and get the message : "position_fill requires constant width"

So I guess to get what I tried to get is impossible, at least using geom_bar.

N West
  • 6,768
  • 25
  • 40
fstevens
  • 1,287
  • 1
  • 17
  • 28

2 Answers2

5

I can do it by preprocessing the data, but not entirely within a single ggplot call.

library("plyr")
mt <- ddply(mtcars, .(cyl, vs), summarise, n=length(cyl))
mt <- ddply(mt, .(cyl), mutate, nfrac = n/sum(n), width = sum(n))
mt$width <- mt$width / max(mt$width)

The mt data set now has everything needed to make the plot:

> mt
  cyl vs  n      nfrac     width
1   4  0  1 0.09090909 0.7857143
2   4  1 10 0.90909091 0.7857143
3   6  0  3 0.42857143 0.5000000
4   6  1  4 0.57142857 0.5000000
5   8  0 14 1.00000000 1.0000000

and the ggplot call would look like

ggplot(mt, aes(x=factor(cyl), fill=factor(vs), y=nfrac)) +
  geom_bar(aes(width=width), position="stack", stat="identity")

It does throw the warning:

Warning message:
position_stack requires constant width: output may be incorrect 

but creates the plot:

enter image description here

Brian Diggs
  • 57,757
  • 13
  • 166
  • 188
1

Is this what you want?

library(ggplot2)
ggplot(mtcars, aes(x=factor(cyl), fill=factor(vs))) + geom_bar(position="fill") + coord_flip()

enter image description here

Thierry
  • 18,049
  • 5
  • 48
  • 66
  • No, what I was trying to do is presented in the post @Geek gave the link. I will try what they explained there. Thanks anyway for your answers. – fstevens Mar 05 '12 at 08:15