Dodging bars in qplot possibly produces wrong totals

14 views
Skip to first unread message

Marco Ghislanzoni

unread,
Nov 29, 2013, 12:12:28 PM11/29/13
to ggp...@googlegroups.com
Dear All,

while experimenting with qplot I stumbled into a strange behavior with dodged bars which seems to produce wrong totals in the chart. Everything works fine as long as the bars are stacked, but a "scaling effect" happens as soon as I dodge the bars. I would like to understand whether it depends on how the data set looks like (but I tried also to melt it to long format and nothing changes) or if something is wrong with the way I do it.

head(dat)
  Country Salesperson Order.Date OrderID Order.Amount
1      UK      Suyama 2003-07-10   10249      1863.40
2     USA     Peacock 2003-07-11   10252      3597.90
3     USA     Peacock 2003-07-12   10250      1552.60
4      UK   Dodsworth 2003-07-15   10255      2490.50
5     USA   Leverling 2003-07-15   10251       654.06
6      UK    Buchanan 2003-07-16   10248       440.00

str(dat)
'data.frame': 799 obs. of  5 variables:
 $ Country     : Factor w/ 2 levels "UK","USA": 1 2 2 1 2 1 2 2 2 1 ...
 $ Salesperson : Ord.factor w/ 9 levels "Peacock"<"Leverling"<..: 8 1 1 7 2 9 2 2 1 9 ...
 $ Order.Date  : Date, format: "2003-07-10" "2003-07-11" ...
 $ OrderID     : int  10249 10252 10250 10255 10251 10248 10253 10256 10257 10254 ...
 $ Order.Amount: num  1863 3598 1553 2490 654 ...

Total orders per sales person:

aggregate(Order.Amount ~ Salesperson, data=dat, sum)
  Salesperson Order.Amount
1     Peacock    225763.68
2   Leverling    201196.27
3     Davolio    182500.09
4      Fuller    162503.78
5    Callahan    123032.67
6        King    116962.99
7   Dodsworth     75048.04
8      Suyama     72527.63
9    Buchanan     68792.25

qplot(x=Salesperson, y=Order.Amount, fill=as.character(Order.Date, "%Y"), geom="bar", stat="identity", data=dat, xlab="Sales Person", ylab="Order Amount (USD)", main="Orders by Sales Person and Year") + theme(axis.text.x = element_text(angle=90, hjust=1, vjust=0)) + guides(fill=guide_legend(title="Year", reverse=FALSE))

And the result above is correct, with the totals of the stacked bars corresponding to the output of aggregate. Now exactly the same, but dodging the bars. The only addition to the version above is position="dodge".

qplot(x=Salesperson, y=Order.Amount, fill=as.character(Order.Date, "%Y"), geom="bar", stat="identity", position="dodge", data=dat, xlab="Sales Person", ylab="Order Amount (USD)", main="Orders by Sales Person and Year") + theme(axis.text.x = element_text(angle=90, hjust=1, vjust=0)) + guides(fill=guide_legend(title="Year", reverse=FALSE))

Not that now the single bars do not add up anymore to the expected totals. Peacock for example made 225K USD total but its total from this chart, by mentally stacking the single bars, only adds up to about 20K. That's 10 times less.

What's wrong? Anything I am missing about "dodging" bars?

Many thanks in advance,
Marco. 

Marco Ghislanzoni

unread,
Nov 29, 2013, 12:59:44 PM11/29/13
to ggp...@googlegroups.com
Just for the records, I found another similar case here.


The answer is indeed that ggplot2 (qplot) will not stack according to one variable and dodge according to another one at the same time. The solution requires to summarize the data in the data frame before plotting. 

Tricky indeed because the bars are actually overlapping within each color instead of being stacked. This can be visualized by specifying an alpha parameter within qplot:

qplot(x=Salesperson, y=value, fill=as.character(Order.Date, "%Y"), geom="bar", stat="identity", position="dodge", alpha=I(1/5), data=data2, xlab="Sales Person", ylab="Order Amount (USD)", main="Orders by Sales Person and Year") + theme(axis.text.x = element_text(angle=90, hjust=1, vjust=0)) + guides(fill=guide_legend(title="Year", reverse=FALSE))

Reply all
Reply to author
Forward
0 new messages